复用机制:Mixin 与继承
Sass 提供两类核心的样式复用机制:Mixin(@mixin / @include,支持参数与内容块)与 继承(@extend、%placeholder,通过合并选择器减少重复)。两者适用场景不同,本文末尾给出对比与选择建议。跨文件使用时需先 @use 引入模块,例如 @use "mixins" as m; 再 @include m.clearfix;(见 模块与控制流)。
一、Mixin(@mixin / @include)
1. 定义与调用(无参数)
最简单的 Mixin 不接收参数,封装一组通用样式。
// 定义
@mixin clearfix {
&::after {
content: "";
display: table;
clear: both;
}
}
// 调用
.container {
@include clearfix;
}
编译后:
.container::after {
content: "";
display: table;
clear: both;
}
适用于无需配置的通用模式(如清除浮动、文本截断等)。
2. 带参数的 Mixin
通过参数使 Mixin 更灵活,可设置默认值。
// 定义:第二个参数有默认值
@mixin button($bg-color, $text-color: white) {
background: $bg-color;
color: $text-color;
padding: 10px 20px;
border-radius: 4px;
}
// 调用
.primary-btn {
@include button(#3498db); // 使用默认文字颜色
}
.secondary-btn {
@include button(#e74c3c, #333); // 两个参数都指定
}
编译结果:
.primary-btn {
background: #3498db;
color: white;
padding: 10px 20px;
border-radius: 4px;
}
.secondary-btn {
background: #e74c3c;
color: #333;
/* ... */
}
支持关键字参数,提高可读性:
@include button($bg-color: #f39c12, $text-color: #fff);
3. 可变参数(...)
当参数个数不确定时,使用 $args... 将所有参数作为列表传递给 Mixin。
// 定义
@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.1));
}
编译后:
.card {
box-shadow:
0 2px 4px rgba(0, 0, 0, 0.1),
0 4px 8px rgba(0, 0, 0, 0.1);
}
可变参还支持将列表值传递给其他 Mixin 或函数。
4. 内容块(@content)
@content 允许调用者向 Mixin 中传递一整块样式代码,实现高度定制。
// 定义:响应式断点 Mixin
@mixin respond-to($breakpoint) {
@media (min-width: $breakpoint) {
@content; // 调用时传入的内容会放置在此处
}
}
// 调用
.sidebar {
width: 100%;
@include respond-to(768px) {
width: 30%; // 这段样式会插入到 @content 位置
}
}
编译后:
.sidebar {
width: 100%;
}
@media (min-width: 768px) {
.sidebar {
width: 30%;
}
}
典型应用:媒体查询封装、主题切换(暗色/亮色)、复杂动画的定制。
5. Mixin 的不足
| 不足 | 说明 | 示例场景 |
|---|---|---|
| CSS 冗余 | 每次 @include 都会完整输出一份样式代码,多次调用会产生重复 CSS | 若在10个地方调用同一个无参数的 clearfix,CSS 中会出现10份完全相同的代码块 |
| 无法合并选择器 | 即使样式完全一样,也不会自动合并 | 与 @extend 不同,Mixin 不会用逗号合并选择器 |
| 调试稍复杂 | 浏览器调试时看到的是展开后的完整代码,不易追溯到 Mixin 源 | 适合配合 sourcemap 使用 |
二、继承与占位符
1. @extend 继承
@extend 允许一个选择器继承另一个选择器的样式,编译后多个选择器会被合并到同一条 CSS 规则中,从而减少冗余。
.message {
padding: 10px;
border: 1px solid #ccc;
}
.success {
@extend .message;
border-color: green;
}
.error {
@extend .message;
border-color: red;
}
编译结果:
.message,
.success,
.error {
padding: 10px;
border: 1px solid #ccc;
}
.success {
border-color: green;
}
.error {
border-color: red;
}
优点:生成的 CSS 体积更小(相同样式只出现一次)。
缺点:
- 不能传递参数,灵活性差。
- 可能会生成较长的选择器列表(当继承链较深时)。
- 不能在
@media内部直接使用@extend继承外部规则(除非该选择器也在同一声明块内)。
2. 占位符选择器 %placeholder
占位符是以 % 开头的特殊选择器,本身不会生成 CSS,只有通过 @extend 被引用时,引用它的选择器才会出现在编译结果中。这使得占位符非常适合定义“抽象基类”,避免污染全局命名空间。
%flex-center {
display: flex;
justify-content: center;
align-items: center;
}
.header {
@extend %flex-center;
}
.footer {
@extend %flex-center;
}
编译结果:
.header,
.footer {
display: flex;
justify-content: center;
align-items: center;
}
占位符的限制:
- 必须定义在顶层作用域(不能在规则内部或媒体查询内部定义)。
- 不支持复合选择器(如
%foo:hover会报错)。 - 不能直接在媒体查询内定义,但可以在媒体查询内
@extend外部定义的占位符。
如何处理响应式场景:通常结合 Mixin 来传递媒体查询逻辑。例如:
%flex-column {
flex-direction: column;
}
@mixin responsive-column {
@media (max-width: 768px) {
@extend %flex-column;
}
}
三、@extend / 占位符 vs @mixin 对比
| 特性 | @extend / 占位符 | @mixin |
|---|---|---|
| 输出方式 | 合并选择器,生成一条共享规则 | 每次调用直接复制样式代码 |
| CSS 体积 | 通常更小(无重复) | 可能因多次调用产生大量重复代码 |
| 参数支持 | ❌ 不支持 | ✅ 支持 |
条件分支(@if) | ❌ 不支持 | ✅ 支持 |
@content 内容块 | ❌ 不支持 | ✅ 支持 |
| 适用场景 | 样式完全相同的静态复用 | 需要动态值或条件逻辑 |
| 可维护性 | 修改一处,所有继承处自动更新 | 需重新编译所有 @include |
选择建议:
- 需要参数或内容块 → 使用
@mixin - 样式完全相同且无需参数 → 优先考虑
@extend或占位符(%placeholder)以减少 CSS 体积 - 不要为每个小组件都使用
@extend,否则选择器列表过长,可能导致 gzip 后体积不减反增,且增加浏览器匹配开销。
四、注意事项与反模式
- 避免链式继承过深:
%a → %b → %c会导致最终选择器列表非常长(.a, .b, .c, .d ...),影响浏览器解析速度。 - 警惕选择器爆炸:如果大量使用
@extend组合,编译后的选择器列表可能包含上百个类名,反而降低性能并增大 CSS 体积。 - 不要在媒体查询内继承外部选择器:Sass 不允许跨
@media作用域继承(会报错)。正确的做法是将公共样式定义为%placeholder,然后在媒体查询内@extend(占位符须在外部定义),或使用 Mixin 配合@content。 - 使用占位符代替普通类继承:当继承的目标不是实际 DOM 中使用的类(即仅作为样式基类),应使用
%placeholder而非普通.class,以避免产生无关的 CSS 类名。
总结
| 特性 | 语法 | 用途 |
|---|---|---|
| Mixin 定义 | @mixin name { ... } | 创建可复用块 |
| Mixin 调用(无参) | @include name; | 使用无参混合 |
| 带参数 | @mixin name($param, $default: val) | 配置化样式 |
| 可变参数 | @mixin name($args...) | 接收不定数量参数 |
| 内容块 | @content + @include name { ... } | 注入自定义样式 |
@extend | .a { @extend .b; } | 合并选择器,减少重复 |
%placeholder | %name { ... } + @extend %name | 抽象基类,不生成无用 CSS |
需要参数或注入代码块时用 Mixin;样式完全相同且无参的静态复用优先评估 @extend 或占位符,以在可维护性与输出 CSS 体积之间取得平衡。
参考文献
| 资料 | 说明 |
|---|---|
| Sass:@mixin | 定义与 @content |
| Sass:@include | 调用 mixin |
| Sass:@extend | 继承与占位符 |
相关文章
Sass 简介与安装
Sass(Syntactically Awesome Style Sheets)是 CSS 预处理器,在 CSS 语法上增加变量、嵌套、混合、模块、控制指令等;有 SCSS 与缩进语法两种源码语法,官方实现为 Dart Sass。
模块与控制流:@use、内置函数、@if/@for/@each
Dart Sass 推荐用 @use/@forward 替代已弃用的 @import;内置 sass:* 模块提供颜色、字符串、列表、Map、数学等函数;@if/@for/@each/@while 用于条件与循环生成样式。
语法基础:变量、嵌套与运算
Sass 语法基础:$ 变量与插值、选择器嵌套与 & 父选择器引用、数学/颜色/字符串运算、三种注释语法及与原生 CSS 嵌套的关系。
Less 基础与核心语法
Less 是 JavaScript 实现的 CSS 预处理器,在 CSS 语法上扩展变量(@)、嵌套、混合、运算与函数,编译为普通 CSS 后由浏览器加载;本文覆盖安装、CLI、构建工具集成与全部核心语法。
颜色与背景
color 设置前景(多为文字)色;background-* 设置元素背景(颜色、图像、渐变)。二者共同决定对比度与视觉层次,直接影响 无障碍 阅读体验。排版中的文本颜色用法见 排版与文本。
工程化集成与扩展
Less 可集成到 Vite、Webpack、Vue CLI 等工具链,实现编译、全局变量注入与路径处理。
Series
sass
3 / 4