.scss 扩展名import './style.scss'// 单行注释(不会编译到 CSS)
/* 多行注释(会编译到 CSS) */
// 颜色变量
$primary-color: #0769fb;
$secondary-color: #6c757d;
$text-color: #333;
$bg-color: #fff;
// 尺寸变量
$spacing-sm: 8px;
$spacing-md: 16px;
$spacing-lg: 24px;
$spacing-xl: 32px;
// 字体变量
$font-size-base: 16px;
$font-size-lg: 20px;
$font-size-sm: 14px;
// 布局变量
$container-width: 1200px;
$sidebar-width: 250px;
.button {
background-color: $primary-color;
padding: $spacing-md;
font-size: $font-size-base;
color: $text-color;
}
$global-color: #000; // 全局变量
.container {
$local-color: #fff; // 局部变量,只在 .container 内可用
color: $local-color;
border-color: $global-color;
}
// 如果变量未定义,使用默认值
$primary-color: #0769fb !default;
.button {
background-color: $primary-color; // 如果未定义,使用 #0769fb
}
// 传统 CSS
.container {
width: 100%;
}
.container .title {
font-size: 20px;
}
.container .title:hover {
color: red;
}
// SCSS 嵌套
.container {
width: 100%;
.title {
font-size: 20px;
&:hover {
color: red;
}
}
}
.button {
background: blue;
// &:hover 编译为 .button:hover
&:hover {
background: darkblue;
}
// &.active 编译为 .button.active
&.active {
background: green;
}
// &::before 编译为 .button::before
&::before {
content: '';
}
// 嵌套中的 & 引用
.icon {
// .button .icon 中的 & 仍然是 .button
&:hover {
// 编译为 .button .icon:hover
}
}
}
// 传统写法
.box {
border-width: 1px;
border-style: solid;
border-color: #ddd;
}
// SCSS 属性嵌套
.box {
border: {
width: 1px;
style: solid;
color: #ddd;
}
// 也可以嵌套伪类
font: {
family: Arial;
size: 16px;
weight: bold;
}
}
.container {
width: 100%;
@media (max-width: 768px) {
width: 100%;
padding: 10px;
.title {
font-size: 18px;
}
}
@media (min-width: 1200px) {
max-width: 1200px;
margin: 0 auto;
}
}
// 定义混入
@mixin flex-center {
display: flex;
align-items: center;
justify-content: center;
}
// 使用混入
.container {
@include flex-center;
height: 100vh;
}
// 定义带参数的混入
@mixin button($bg-color, $text-color: white) {
background-color: $bg-color;
color: $text-color;
padding: 12px 24px;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s;
&:hover {
background-color: darken($bg-color, 10%);
}
}
// 使用
.btn-primary {
@include button(#0769fb);
}
.btn-danger {
@include button(#dc3545);
}
.btn-custom {
@include button(#28a745, #fff);
}
@mixin card($padding: 16px, $shadow: true) {
padding: $padding;
border-radius: 8px;
@if $shadow {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
}
.card {
@include card; // 使用默认值
}
.card-large {
@include card(24px, false); // 自定义参数
}
@mixin responsive($breakpoint) {
@media (max-width: $breakpoint) {
@content; // 插入传入的内容
}
}
.container {
width: 100%;
@include responsive(768px) {
width: 100%;
padding: 10px;
}
}
$primary: #0769fb;
.button {
// 变亮/变暗
background: lighten($primary, 20%);
border-color: darken($primary, 10%);
// 调整饱和度
background: saturate($primary, 20%);
background: desaturate($primary, 20%);
// 调整透明度
background: rgba($primary, 0.8);
background: fade-in($primary, 0.2);
background: fade-out($primary, 0.2);
// 混合颜色
background: mix($primary, white, 50%);
// 调整色调
background: adjust-hue($primary, 30deg);
// 互补色
border-color: complement($primary);
}
$font-family: 'Arial';
.text {
// 转大写
text-transform: to-upper-case($font-family);
// 转小写
text-transform: to-lower-case($font-family);
// 引用字符串
content: quote('Hello');
// 取消引用
font-family: unquote('Arial');
}
.container {
// 百分比
width: percentage(2/3); // 66.666667%
// 四舍五入
font-size: round(18.7px); // 19px
// 向上取整
padding: ceil(18.2px); // 19px
// 向下取整
margin: floor(18.9px); // 18px
// 绝对值
left: abs(-10px); // 10px
// 最小值/最大值
width: min(100px, 200px); // 100px
height: max(50px, 100px); // 100px
}
// 计算 rem
@function calculate-rem($pixels) {
@return $pixels / 16px * 1rem;
}
.title {
font-size: calculate-rem(24px); // 1.5rem
}
// 间距函数
@function spacing($multiplier) {
@return $multiplier * 8px;
}
.container {
padding: spacing(2); // 16px
margin: spacing(3); // 24px
}
// 颜色对比度函数
@function get-text-color($bg-color) {
@if lightness($bg-color) > 50% {
@return #000; // 浅色背景用黑色文字
} @else {
@return #fff; // 深色背景用白色文字
}
}
.button {
background: $primary-color;
color: get-text-color($primary-color);
}
// 定义占位符选择器(%)
%button-base {
padding: 12px 24px;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s;
border: none;
}
// 继承
.btn-primary {
@extend %button-base;
background-color: #0769fb;
color: white;
}
.btn-secondary {
@extend %button-base;
background-color: #6c757d;
color: white;
}
// 混入:会复制代码到每个类中
@mixin button-mixin {
padding: 12px;
}
.btn1 { @include button-mixin; }
.btn2 { @include button-mixin; }
// 编译后:两个类都有 padding: 12px
// 继承:会合并选择器
%button-extend {
padding: 12px;
}
.btn1 { @extend %button-extend; }
.btn2 { @extend %button-extend; }
// 编译后:.btn1, .btn2 { padding: 12px; }
@import 'variables';
@import 'mixins';
// _variables.scss
$primary-color: #0769fb;
$spacing: 16px;
// _mixins.scss
@mixin flex-center {
display: flex;
align-items: center;
justify-content: center;
}
// main.scss
@use 'variables' as vars;
@use 'mixins' as mix;
.container {
color: vars.$primary-color;
padding: vars.$spacing;
@include mix.flex-center;
}
// 或者不使用命名空间
@use 'variables';
@use 'mixins';
.container {
color: variables.$primary-color;
@include mixins.flex-center;
}
// _all.scss
@forward 'variables';
@forward 'mixins';
// main.scss
@use 'all';
.container {
color: all.$primary-color;
@include all.flex-center;
}
// _variables.scss
$button-colors: (
'primary': #0769fb,
'success': #28a745,
'danger': #dc3545,
'warning': #ffc107
);
$button-padding: 12px 24px;
$button-radius: 4px;
// _mixins.scss
@mixin button-base {
padding: $button-padding;
border-radius: $button-radius;
border: none;
cursor: pointer;
font-size: 16px;
transition: all 0.3s;
&:hover {
transform: translateY(-2px);
}
&:active {
transform: translateY(0);
}
}
@mixin button-variant($color-name) {
$color: map-get($button-colors, $color-name);
background-color: $color;
color: white;
&:hover {
background-color: darken($color, 10%);
}
&:active {
background-color: darken($color, 15%);
}
}
// buttons.scss
@use 'variables' as vars;
@use 'mixins' as mix;
.button {
@include mix.button-base;
@each $name, $color in vars.$button-colors {
&.#{$name} {
@include mix.button-variant($name);
}
}
}
// _variables.scss
$breakpoints: (
'sm': 576px,
'md': 768px,
'lg': 992px,
'xl': 1200px
);
$grid-columns: 12;
// _mixins.scss
@mixin respond-to($breakpoint) {
$value: map-get($breakpoints, $breakpoint);
@if $value {
@media (min-width: $value) {
@content;
}
}
}
@mixin grid-column($columns) {
width: percentage($columns / $grid-columns);
@include respond-to('md') {
width: percentage($columns / $grid-columns);
}
}
// grid.scss
@use 'variables' as vars;
@use 'mixins' as mix;
.container {
display: flex;
flex-wrap: wrap;
@include respond-to('md') {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: 16px;
}
}
@for $i from 1 through vars.$grid-columns {
.col-#{$i} {
@include mix.grid-column($i);
}
}
// _themes.scss
$themes: (
'light': (
'bg': #fff,
'text': #333,
'primary': #0769fb
),
'dark': (
'bg': #1a1a1a,
'text': #fff,
'primary': #4a9eff
)
);
@function theme($theme-name, $key) {
$theme: map-get($themes, $theme-name);
@return map-get($theme, $key);
}
// main.scss
@use 'themes' as t;
body {
background-color: t.theme('light', 'bg');
color: t.theme('light', 'text');
&.dark-theme {
background-color: t.theme('dark', 'bg');
color: t.theme('dark', 'text');
}
}
.button {
background-color: t.theme('light', 'primary');
.dark-theme & {
background-color: t.theme('dark', 'primary');
}
}
// _animations.scss
@mixin fade-in($duration: 0.3s) {
animation: fadeIn $duration ease-in-out;
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
}
@mixin slide-in($direction: left, $distance: 100px, $duration: 0.3s) {
$transform: null;
@if $direction == 'left' {
$transform: translateX(-$distance);
} @else if $direction == 'right' {
$transform: translateX($distance);
} @else if $direction == 'up' {
$transform: translateY(-$distance);
} @else {
$transform: translateY($distance);
}
animation: slideIn $duration ease-out;
@keyframes slideIn {
from {
transform: $transform;
opacity: 0;
}
to {
transform: translate(0, 0);
opacity: 1;
}
}
}
// 使用
.modal {
@include fade-in(0.5s);
}
.sidebar {
@include slide-in('left', 200px, 0.4s);
}
styles/
├── _variables.scss # 变量
├── _mixins.scss # 混入
├── _functions.scss # 函数
├── _base.scss # 基础样式
├── _components.scss # 组件样式
└── main.scss # 主文件
// 变量:使用 kebab-case
$primary-color: #0769fb;
$spacing-base: 8px;
// 混入:使用 kebab-case
@mixin flex-center { }
@mixin button-variant { }
// 函数:使用 kebab-case
@function calculate-rem { }
// ❌ 不好:嵌套太深
.container {
.wrapper {
.content {
.title {
.text {
color: red;
}
}
}
}
}
// ✅ 好:保持 3-4 层以内
.container {
.content {
.title {
color: red;
}
}
}
// ✅ 好:使用变量
$primary: #0769fb;
.button { background: $primary; }
// ❌ 不好:硬编码
.button { background: #0769fb; }
// 混入:用于需要参数的样式
@mixin button($color) {
background: $color;
}
// 继承:用于不需要参数的通用样式
%reset-list {
margin: 0;
padding: 0;
list-style: none;
}
// ✅ 推荐
@use 'variables';
// ❌ 已废弃
@import 'variables';
@mixin clearfix {
&::after {
content: '';
display: table;
clear: both;
}
}
@mixin text-ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
@mixin text-ellipsis-multi($lines: 2) {
display: -webkit-box;
-webkit-line-clamp: $lines;
-webkit-box-orient: vertical;
overflow: hidden;
}
@mixin flex-center {
display: flex;
align-items: center;
justify-content: center;
}
@mixin absolute-center {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
$breakpoints: (
'sm': 576px,
'md': 768px,
'lg': 992px,
'xl': 1200px
);
@mixin respond-to($breakpoint) {
$value: map-get($breakpoints, $breakpoint);
@if $value {
@media (min-width: $value) {
@content;
}
}
}
$width: 100px;
@debug "Width is: #{$width}";
@function calculate-rem($pixels) {
@if unit($pixels) != 'px' {
@warn "Expected pixels, got #{unit($pixels)}";
}
@return $pixels / 16px * 1rem;
}
@mixin debug-variable($var) {
&::before {
content: '#{$var}';
}
}
SCSS 的核心优势:
记住:功能强大,但要适度使用,保持代码简洁易读!