目录
- SCSS 简介与环境搭建
- 变量:样式数据的核心管理
- 嵌套:让代码结构跟随HTML
- 混合(Mixin):代码复用的利器
- 继承(@extend):样式共享的高效方式
- 运算与函数:动态生成样式
- 控制指令:@if、@for、@each、@while
- 模块化系统:@use 与 @forward(现代推荐)
- 实战场景:响应式设计与全局配置
- 常见错误与避坑指南
- 总结与进阶建议
1. SCSS 简介与环境搭建
1.1 什么是 SCSS?
SCSS 是 CSS 的“增强版”,写法上与 CSS 高度相似(保留 {} 和 ;),但多了很多能提升效率的功能。它是 Sass(世界上最成熟、最稳定的专业级 CSS 扩展语言)的一种语法格式,与之对应的还有缩进式的 Sass 语法,但 SCSS 因为完全兼容 CSS 语法(任何合法的 CSS 文件都能直接改成 .scss 文件使用),成为了绝对的主流。
核心概念:我们编写 .scss 文件,然后使用 Sass 预处理器将其编译为浏览器能够识别的 .css 文件,最终应用到项目中。
1.2 环境搭建
Step 1:安装 Sass 预处理器
安装前提,装好node 和 npm 环境
node-vnpm-vStep 2:全局安装
适用于命令行编译 SCSS 文件,可以通过命令行将.scss编译为.css
npminstall-gsass sass--versionStep 3:安装 Sass 预处理器
在项目中安装 sass 依赖:
# 使用 npmnpminstallsass --save-dev# 使用 yarnyarnaddsass-D# 使用 pnpmpnpmaddsass-DStep 4:在 Vue/Vite 项目中启用 SCSS
在vite.config.js中进行基础配置:
// vite.config.jsimport{defineConfig}from'vite'exportdefaultdefineConfig({css:{preprocessorOptions:{scss:{// 基础配置(全局注入详见第9章)}}}})Step 5:编译测试
创建一个style.scss文件:
$primary-color: #42b983; body { background: $primary-color; h1 { color: white; } }运行编译命令:
npx sass style.scss style.css生成style.css:
body{background:#42b983;}body h1{color:white;}2. 变量:样式数据的核心管理
2.1 变量的定义与使用
SCSS 中用$符号开头定义变量,可以在整个样式表中引用。
// 定义基础变量 $color-primary: #0081ff; // 主色 $color-secondary: #f5f5f5; // 辅助色 $font-size-base: 14px; // 基础字体大小 $border-radius: 4px; // 圆角大小 $spacing-unit: 8px; // 间距单位 $transition-duration: 0.25s; // 过渡时长 // 引用变量 .btn-primary { background-color: $color-primary; color: #fff; font-size: $font-size-base; border-radius: $border-radius; padding: $spacing-unit * 2 $spacing-unit * 3; // 支持数学运算 transition: background-color $transition-duration ease; } .card { background-color: #fff; border: 1px solid $color-secondary; border-radius: $border-radius; }2.2 变量的作用域
SCSS 变量支持块级作用域:在嵌套规则内部定义的变量是局部变量,外部无法访问。
$global-color: red; // 全局变量 .container { $local-color: blue; // 局部变量,仅在此规则内有效 color: $global-color; // ✅ 可以访问全局变量 background: $local-color; // ✅ 可以访问局部变量 } .sidebar { color: $global-color; // ✅ 可以访问全局变量 background: $local-color; // ❌ 错误!局部变量外部无法访问 }强制转换为全局变量:使用!global标志可以将局部变量提升为全局变量。
.container { $theme-color: green !global; // 强制设为全局变量 color: $theme-color; } .sidebar { color: $theme-color; // ✅ 现在可以访问了 }2.3 默认变量!default
当变量可能被重复定义时,使用!default设置默认值:如果该变量之前已被赋值,则使用已有值;否则使用默认值。
// _variables.scss $primary-color: #0081ff !default; $spacing: 16px !default; // 主题覆盖文件 $primary-color: #ff5722; // 覆盖默认值 // 使用时会得到 #ff5722 .button { background: $primary-color; }2.4 构建间距比例尺系统
利用变量和 map 构建完整的设计系统:
$spacing-base: 4px; $spacing-scale: ( 'xs': $spacing-base, // 4px 'sm': $spacing-base * 2, // 8px 'md': $spacing-base * 4, // 16px 'lg': $spacing-base * 6, // 24px 'xl': $spacing-base * 8, // 32px '2xl': $spacing-base * 12 // 48px ); .card { margin-bottom: map-get($spacing-scale, 'md'); // 16px padding: map-get($spacing-scale, 'lg'); // 24px } .section { padding: map-get($spacing-scale, 'xl'); // 32px }3. 嵌套:让代码结构跟随 HTML
3.1 选择器嵌套
原生 CSS 写嵌套结构时选择器会越来越长,SCSS 的嵌套语法允许直接跟着 HTML 层级书写。
// SCSS 写法 .header { width: 100%; padding: 20px 0; .nav { display: flex; justify-content: space-between; .list { display: flex; gap: 20px; .item { color: #333; cursor: pointer; } } } }编译后的 CSS:
.header{width:100%;padding:20px 0;}.header .nav{display:flex;justify-content:space-between;}.header .nav .list{display:flex;gap:20px;}.header .nav .list .item{color:#333;cursor:pointer;}3.2 父选择器引用&
&代表嵌套规则外层的父选择器,常用于伪类和修饰符。
// 错误写法:没有使用 & .main1 { a { :hover { color: red; } // 编译后 .main1 a :hover(中间有空格) } } // 正确写法:使用 & .main1 { a { &:hover { color: red; } // 编译后 .main1 a:hover } }更丰富的&用法:
.button { background-color: blue; &:hover { background-color: darkblue; // .button:hover } &.active { font-weight: bold; // .button.active } &-large { padding: 16px 24px; // .button-large } &-small { padding: 8px 12px; // .button-small } .icon { margin-right: 8px; // .button .icon(不使用 &) } }3.3 属性嵌套
对于相同前缀的属性(如font-*、border-*),可以进行属性嵌套:
// SCSS .funky { font: 20px/24px { family: fantasy; weight: bold; } } .text { font: { size: 12px; family: fantasy; } border: { radius: 4px; width: 1px; style: solid; color: #ccc; } }编译后的 CSS:
.funky{font:20px/24px;font-family:fantasy;font-weight:bold;}.text{font-size:12px;font-family:fantasy;border-radius:4px;border-width:1px;border-style:solid;border-color:#ccc;}3.4 群组嵌套
同时为多个选择器应用相同样式:
#content { h1, h2, h3, h4 { border: solid; margin: 0 0 10px 0; } }编译结果:
#content h1, #content h2, #content h3, #content h4{border:solid;margin:0 0 10px 0;}最佳实践:嵌套深度不宜超过 3 层,否则编译后的 CSS 选择器过长,影响性能和可维护性。
4. 混合(Mixin):代码复用的利器
4.1 基础用法
混合指令(Mixin)用于定义可重复使用的样式,可以包含所有的 CSS 规则,甚至通过参数功能引入变量。
// 定义无参数混合 @mixin flex-center { display: flex; justify-content: center; align-items: center; } @mixin large-text { font: { family: Arial; size: 20px; weight: bold; } color: #ff0000; } // 使用混合 .container { @include flex-center; } .page-title { @include large-text; padding: 4px; margin-top: 10px; }4.2 带参数的混合(核心功能)
// 带参数的混合(推荐添加默认值) @mixin link-colors($normal, $hover, $visited) { color: $normal; &:hover { color: $hover; } &:visited { color: $visited; } } @mixin rounded-button($radius: 4px, $bg: $color-primary, $color: white) { border-radius: $radius; background-color: $bg; color: $color; padding: 8px 16px; border: none; cursor: pointer; } // 调用方式 .link { @include link-colors(blue, red, purple); } .btn-primary { @include rounded-button; // 使用默认值 } .btn-large { @include rounded-button(8px, #28a745, white); // 覆盖所有参数 } .btn-small { @include rounded-button($radius: 2px); // 只覆盖圆角 }4.3 可变参数
当不确定参数数量时,使用...接收可变参数:
@mixin box-shadow($shadows...) { box-shadow: $shadows; } .card { @include box-shadow(0 2px 4px rgba(0,0,0,0.1), 0 4px 8px rgba(0,0,0,0.05)); } // 配合 transition 使用 @mixin transitions($properties...) { transition: $properties; } .button { @include transitions(background 0.3s ease, transform 0.2s ease); }4.4 内容块传递(@content)
使用@content可以让混合接收一段自定义样式,极大提升了灵活性:
// 响应式断点混合 @mixin respond-to($breakpoint) { @media (min-width: $breakpoint) { @content; } } // 使用示例 .sidebar { width: 100%; @include respond-to(768px) { width: 300px; } @include respond-to(1200px) { width: 400px; } } // 更实用的断点混合 $breakpoints: ( 'sm': 576px, 'md': 768px, 'lg': 992px, 'xl': 1200px ); @mixin media-up($breakpoint) { @if map-has-key($breakpoints, $breakpoint) { @media (min-width: map-get($breakpoints, $breakpoint)) { @content; } } } .grid { display: grid; grid-template-columns: 1fr; @include media-up('md') { grid-template-columns: repeat(2, 1fr); } @include media-up('lg') { grid-template-columns: repeat(3, 1fr); } }5. 继承(@extend):样式共享的高效方式
5.1 基础继承
当一个样式与另一个样式几乎完全相同,只有少量差异时,使用@extend可以避免代码冗余。
// 基础样式 .contanier1 { font-size: 24px; font-weight: bold; color: green; } // 继承并覆盖/扩展 .contanier2 { @extend .contanier1; color: red; // 覆盖 color 属性 } .contanier3 { @extend .contanier1; font-size: 30px; // 覆盖 font-size }编译后:
.contanier1, .contanier2, .contanier3{font-size:24px;font-weight:bold;color:green;}.contanier2{color:red;}.contanier3{font-size:30px;}5.2 占位符选择器(%)
占位符选择器以%开头,只有当被@extend继承时才会生成 CSS,否则完全不会出现在编译结果中。
// 定义占位符 %message-shared { border: 1px solid #ccc; padding: 10px; margin: 10px 0; } %message-highlight { background-color: #f8f9fa; } // 使用继承 .message-success { @extend %message-shared; @extend %message-highlight; color: green; } .message-error { @extend %message-shared; color: red; }5.3 Mixin vs Extend 选择指南
| 特性 | @mixin | @extend |
|---|---|---|
| 代码体积 | 每次调用都会复制代码 | 选择器合并,代码更精简 |
| 灵活性 | 支持参数,非常灵活 | 不支持参数 |
| 适用场景 | 需要参数化定制时 | 样式完全相同,仅语义不同时 |
| 性能考虑 | 调用多次会增加文件大小 | 文件更小,但可能影响选择器特异性 |
// 推荐使用 mixin 的场景:需要参数 @mixin button-variant($color, $bg) { color: $color; background: $bg; &:hover { background: darken($bg, 10%); } } // 推荐使用 extend 的场景:样式完全一致 %visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); border: 0; } .skip-link { @extend %visually-hidden; } .screen-reader-text { @extend %visually-hidden; }6. 运算与函数:动态生成样式
6.1 数学运算
SCSS 支持标准的数学运算:+、-、*、/、%。
$base-font: 16px; $base-spacing: 8px; .container { font-size: $base-font; // 16px padding: $base-spacing * 2; // 16px margin: $base-spacing / 2; // 4px // 混合单位运算(需要确保单位兼容) width: 100% - 20px; // 注意:/ 在 CSS 属性中原本就存在,SCSS 有特殊规则 font: $base-font / 2; // 使用括号避免歧义 font: ($base-font / 2); // 明确为除法 } // 间距系统 $spacing-unit: 4px; .section { padding: $spacing-unit * 6; // 24px margin-bottom: $spacing-unit * 4; // 16px }6.2 字符串运算
使用+进行字符串拼接:
$base-url: "/assets/images/"; .icon { background-image: url($base-url + "icon.png"); } // 使用插值语法 #{} 在字符串中嵌入变量 $name: "button"; $state: "hover"; .#{$name} { &-#{$state} { color: red; } }6.3 颜色函数
Sass 提供了丰富的颜色处理函数:
$brand-primary: #3a86ff; .button-primary { background-color: $brand-primary; &:hover { background-color: darken($brand-primary, 10%); // 加深 10% } &:active { background-color: lighten($brand-primary, 5%); // 提亮 5% } } // 透明度处理 .overlay { background-color: rgba($brand-primary, 0.5); background-color: transparentize($brand-primary, 0.5); // 同上 } // 颜色混合 .mix-color { background-color: mix(red, blue, 50%); // 紫色(红蓝各半) } // 饱和度调整 .subtle-bg { background-color: desaturate($brand-primary, 30%); // 降低饱和度 }6.4 自定义函数(@function)
使用@function定义自己的函数,返回计算后的值:
// 定义像素转 rem 函数 @function px-to-rem($px-value, $base-font: 16px) { @return ($px-value / $base-font) * 1rem; } // 计算间距函数 @function spacing($multiplier) { @return $spacing-base * $multiplier; } // 使用示例 $spacing-base: 4px; .heading { font-size: px-to-rem(32px); // 2rem margin-bottom: spacing(6); // 24px } // 更复杂的函数:计算亮度 @function is-light($color) { $red: red($color); $green: green($color); $blue: blue($color); $brightness: (($red * 299) + ($green * 587) + ($blue * 114)) / 1000; @return $brightness > 128; } // 根据背景色自动选择文字颜色 @function text-color($bg-color) { @if is-light($bg-color) { @return #333; } @else { @return #fff; } } .button-auto { background: $brand-primary; color: text-color($brand-primary); }7. 控制指令:@if、@for、@each、@while
7.1 @if 条件判断
@if指令允许根据条件进行分支。
@mixin theme-aware($theme) { @if $theme == 'light' { background: white; color: black; } @else if $theme == 'dark' { background: #1a1a1a; color: white; } @else { background: gray; color: white; } } .container { @include theme-aware('dark'); } // 结合响应式使用 @mixin responsive-font($size) { @if $size == 'small' { font-size: 12px; } @else if $size == 'medium' { font-size: 16px; } @else { font-size: 20px; } }7.2 @for 循环
@for循环用于生成规律重复的样式。through包含结束值,to不包含结束值。
// 使用 through(包含结束值 3) @for $i from 1 through 3 { .col-#{$i} { width: percentage($i / 3); } } // 生成 .col-1 { width: 33.33333%; } // .col-2 { width: 66.66667%; } // .col-3 { width: 100%; } // 使用 to(不包含结束值 3) @for $i from 1 to 3 { .item-#{$i} { font-size: #{$i}em; } } // 生成 .item-1 { font-size: 1em; } // .item-2 { font-size: 2em; } // 实际应用:延迟动画 @for $i from 1 through 10 { .animate-item:nth-child(#{$i}) { animation-delay: #{$i * 0.1}s; } } // 网格系统 @for $i from 1 through 12 { .grid-#{$i} { width: calc(100% / 12 * #{$i}); } }7.3 @each 循环
@each用于遍历列表或 map 中的值。
// 遍历列表 $colors: red, blue, green, yellow; @each $color in $colors { .bg-#{$color} { background-color: $color; } } // 遍历 map(推荐用于主题系统) $theme-colors: ( 'primary': #007bff, 'success': #28a745, 'warning': #ffc107, 'danger': #dc3545 ); @each $name, $color in $theme-colors { .btn-#{$name} { background-color: $color; border-color: $color; &:hover { background-color: darken($color, 10%); } } } // 同时遍历多个值 $icons: ('home', 'home'), ('user', 'user'), ('settings', 'cog'); @each $name, $glyph in $icons { .icon-#{$name}:before { content: $glyph; } }7.4 @while 循环
@while循环在条件为真时持续执行(使用频率较低,一般场景下@for和@each已足够):
$i: 6; @while $i > 0 { .item-#{$i} { z-index: $i; } $i: $i - 1; } // 生成 .item-6 { z-index: 6; } 到 .item-1 { z-index: 1; }8. 模块化系统:@use 与 @forward(现代推荐)
8.1 为什么弃用 @import?
SCSS 中的@import已被标记为废弃,将在未来版本中移除。原因如下:
- 全局引入所有变量、混合和函数,导致命名冲突
- 无法控制加载顺序
- 重复导入时无法去重
新的模块系统(@use和@forward)通过显式命名空间和按需加载解决了这些问题。
8.2 @use:模块化导入(推荐)
@use将另一个 SCSS 文件当作“模块”加载,默认通过命名空间访问变量、函数和混入。
// _variables.scss $primary: #0b81ff !default; $secondary: #6c757d !default; @mixin btn { padding: 8px 12px; border-radius: 8px; } // _typography.scss $font-family-base: 'Inter', sans-serif; @function px-to-rem($px) { @return ($px / 16px) * 1rem; } // main.scss - 使用 @use @use 'variables' as vars; // 起别名 @use 'typography' as type; // 起别名 .button { color: vars.$primary; // 通过命名空间访问变量 font-family: type.$font-family-base; @include vars.btn(); // 通过命名空间调用 mixin } .title { font-size: type.px-to-rem(24px); // 通过命名空间调用函数 }使用as *去除命名空间(谨慎使用):
// 去除命名空间(全局暴露,可能导致冲突) @use 'variables' as *; .button { color: $primary; // 直接使用,不加前缀 @include btn(); }使用with配置默认变量:
// 配置模块的 !default 变量 @use 'variables' as vars with ( $primary: #0052d9, // 覆盖默认值 $secondary: #666666 );8.3 @forward:聚合导出
@forward用于把若干模块“转发”出去,创建一个统一的入口文件(类似 barrel 文件)。
// styles/_index.scss —— 统一出口 @forward 'variables'; @forward 'mixins' show flex-center, grid; // 只暴露指定的 mixin @forward 'functions' hide px-to-rem; // 隐藏指定的函数 @forward 'colors' as color-*; // 导出时添加前缀 // main.scss —— 使用统一出口 @use 'styles' as style; .button { color: style.$color-primary; // 通过统一入口访问 @include style.flex-center(); }8.4 完整的模块化项目结构示例
styles/ ├── _variables.scss # 变量定义 ├── _mixins.scss # 混合定义 ├── _functions.scss # 函数定义 ├── _index.scss # 统一出口(聚合转发) └── components/ ├── _button.scss ├── _card.scss └── _index.scss_index.scss(统一出口):
@forward 'variables'; @forward 'mixins'; @forward 'functions';components/_button.scss:
@use '../index' as *; // 导入所有样式模块 .button { background: $primary; border-radius: $border-radius; @include transition(); }9. 实战场景:响应式设计与全局配置
9.1 响应式设计最佳实践
基础用法:媒体查询嵌套
Sass 允许将@media直接嵌套在选择器内部,编译时会自动提升到最外层。
.sidebar { width: 100%; @media (min-width: 768px) { width: 50%; } @media (min-width: 1200px) { width: 320px; } }使用变量管理断点
// _breakpoints.scss $breakpoint-sm: 576px; $breakpoint-md: 768px; $breakpoint-lg: 992px; $breakpoint-xl: 1200px; $breakpoint-xxl: 1400px; // 使用变量 .container { width: 100%; @media (min-width: $breakpoint-md) { width: 750px; } @media (min-width: $breakpoint-lg) { width: 970px; } @media (min-width: $breakpoint-xl) { width: 1170px; } }封装响应式混合(企业级方案)
// _responsive.scss $breakpoints: ( 'xs': 0, 'sm': 576px, 'md': 768px, 'lg': 992px, 'xl': 1200px, 'xxl': 1400px ); // 向上响应(min-width) @mixin up($breakpoint) { $value: map-get($breakpoints, $breakpoint); @if $value != null { @media (min-width: $value) { @content; } } } // 向下响应(max-width) @mixin down($breakpoint) { $value: map-get($breakpoints, $breakpoint); @if $value != null { @media (max-width: $value - 1) { @content; } } } // 区间响应 @mixin between($min, $max) { $min-value: map-get($breakpoints, $min); $max-value: map-get($breakpoints, $max); @if $min-value != null and $max-value != null { @media (min-width: $min-value) and (max-width: $max-value - 1) { @content; } } } // 使用示例 .card { padding: 16px; @include up('md') { padding: 24px; } @include up('lg') { padding: 32px; display: flex; } } .hide-on-mobile { @include down('md') { display: none; } }CSS 自定义属性实现响应式变量
Sass 变量是编译时确定的静态值,无法在媒体查询中动态变化。要实现响应式变量,需要使用 CSS 自定义属性(CSS 变量)。
// 定义断点 $breakpoint-md: 768px; $breakpoint-xl: 1200px; // 响应式 mixin @mixin larger-than($breakpoint) { @media (min-width: $breakpoint) { @content; } } // 在根元素定义响应式 CSS 变量 :root { --header-height: 60px; --container-padding: 16px; @include larger-than($breakpoint-md) { --header-height: 80px; --container-padding: 24px; } @include larger-than($breakpoint-xl) { --header-height: 120px; --container-padding: 32px; } } // 使用 CSS 变量 .header { height: var(--header-height); } .container { padding: var(--container-padding); } // CSS 变量与 Sass 变量结合使用 $colors: ( 'primary': #007bff, 'success': #28a745, 'danger': #dc3545 ); :root { @each $name, $color in $colors { --color-#{$name}: #{$color}; } } .button-primary { background-color: var(--color-primary); }9.2 Vite 全局注入 SCSS
在 Vite 项目中,通过配置css.preprocessorOptions.scss.additionalData可以将 SCSS 变量和混合全局注入。
// vite.config.jsimport{defineConfig}from'vite'exportdefaultdefineConfig({css:{preprocessorOptions:{scss:{additionalData:`@use "@/styles/variables.scss" as vars; @use "@/styles/mixins.scss" as *;`}}}})注意事项:additionalData中使用@use时,需要在组件中通过命名空间访问:
// 在 Vue 组件中 <style lang="scss"> .button { color: vars.$primary; // 需要命名空间前缀 @include flex-center(); // as * 时可以直接调用 } </style>最佳实践:创建聚合入口文件
// src/styles/index.scss @forward 'variables'; @forward 'mixins'; @forward 'functions';// vite.config.jsexportdefaultdefineConfig({css:{preprocessorOptions:{scss:{additionalData:`@use "@/styles/index" as *;`}}}})9.3 完整项目示例:主题切换系统
// _themes.scss $themes: ( light: ( bg-primary: #ffffff, bg-secondary: #f5f5f5, text-primary: #333333, text-secondary: #666666, border: #e0e0e0 ), dark: ( bg-primary: #1a1a1a, bg-secondary: #2d2d2d, text-primary: #ffffff, text-secondary: #b3b3b3, border: #404040 ) ); @mixin themed() { @each $theme, $map in $themes { .theme-#{$theme} & { $theme-map: () !global; @each $key, $value in $map { $theme-map: map-merge($theme-map, ($key: $value)) !global; } @content; $theme-map: null !global; } } } @function t($key) { @return map-get($theme-map, $key); } // 使用示例 .card { @include themed() { background: t(bg-primary); color: t(text-primary); border: 1px solid t(border); } }10. 常见错误与避坑指南
10.1 变量作用域陷阱
// ❌ 错误:局部变量在外部无法访问 .nav { $nav-color: blue; color: $nav-color; // ✅ } .footer { color: $nav-color; // ❌ Error: Undefined variable } // ✅ 正确:需要时使用 !global 或将变量定义在顶层 $global-nav-color: blue;10.2 父选择器误用
// ❌ 错误:缺少 & 导致生成错误的选择器 .button { :hover { color: red; } // 编译为 .button :hover(中间有空格) } // ✅ 正确:使用 & 引用父选择器 .button { &:hover { color: red; } // 编译为 .button:hover }10.3 @import vs @use 选择
// ⚠️ 旧方式(已弃用,会产生警告) @import 'variables'; @import 'mixins'; // ✅ 新方式(推荐) @use 'variables' as vars; @use 'mixins'; .button { color: vars.$primary; @include mixins.flex-center(); }10.4 过度嵌套
// ❌ 不推荐:嵌套过深(4层以上) .header { .nav { .menu { .item { .link { color: blue; // 选择器过于具体,难以覆盖 } } } } } // ✅ 推荐:保持嵌套不超过 3 层 .header { .nav-menu { .menu-item { .link { color: blue; } } } }10.5 媒体查询变量误用
// ❌ 错误:在媒体查询中修改 Sass 变量不会影响外部 $padding: 16px; .container { padding: $padding; @media (min-width: 768px) { $padding: 32px; // 这不会改变外部的 $padding padding: $padding; // 在媒体查询内有效,但编译后是独立值 } } // ✅ 正确:直接覆盖样式,或使用 CSS 自定义属性 .container { padding: 16px; @media (min-width: 768px) { padding: 32px; } }10.6 变量命名规范建议
// ❌ 差:基于具体值命名 $blue: #0081ff; $red: #ff5722; // ✅ 好:基于用途命名 $color-primary: #0081ff; $color-secondary: #ff5722; $color-accent: #00c853;