Sass 混合宏 #
什么是混合宏? #
混合宏(Mixin)是 Sass 中最强大的功能之一,它允许你定义可复用的样式块,并可以接收参数。类似于编程语言中的函数。
scss
// 定义混合宏
@mixin button-base {
display: inline-block;
padding: 10px 20px;
border: none;
cursor: pointer;
}
// 使用混合宏
.button {
@include button-base;
background-color: blue;
}
基本语法 #
定义混合宏 #
scss
@mixin mixin-name {
// 样式内容
}
使用混合宏 #
scss
selector {
@include mixin-name;
}
无参数混合宏 #
scss
@mixin flex-center {
display: flex;
justify-content: center;
align-items: center;
}
.container {
@include flex-center;
height: 100vh;
}
.modal {
@include flex-center;
position: fixed;
}
// 编译后
.container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.modal {
display: flex;
justify-content: center;
align-items: center;
position: fixed;
}
带参数混合宏 #
单个参数 #
scss
@mixin border-radius($radius) {
border-radius: $radius;
}
.box {
@include border-radius(10px);
}
.card {
@include border-radius(8px);
}
// 编译后
.box {
border-radius: 10px;
}
.card {
border-radius: 8px;
}
多个参数 #
scss
@mixin box($width, $height, $bg-color) {
width: $width;
height: $height;
background-color: $bg-color;
}
.element {
@include box(100px, 100px, red);
}
// 编译后
.element {
width: 100px;
height: 100px;
background-color: red;
}
默认参数值 #
scss
@mixin button($padding: 10px 20px, $radius: 4px) {
padding: $padding;
border-radius: $radius;
}
.btn-default {
@include button; // 使用默认值
}
.btn-large {
@include button(15px 30px, 8px); // 自定义值
}
.btn-small {
@include button(5px 10px); // 只覆盖第一个参数
}
// 编译后
.btn-default {
padding: 10px 20px;
border-radius: 4px;
}
.btn-large {
padding: 15px 30px;
border-radius: 8px;
}
.btn-small {
padding: 5px 10px;
border-radius: 4px;
}
关键字参数 #
scss
@mixin box-shadow($x: 0, $y: 4px, $blur: 8px, $color: rgba(0, 0, 0, 0.1)) {
box-shadow: $x $y $blur $color;
}
.card {
@include box-shadow($blur: 12px, $color: rgba(0, 0, 0, 0.2));
}
// 编译后
.card {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
可变参数 #
使用 ... 接收任意数量的参数:
scss
@mixin box-shadow($shadows...) {
box-shadow: $shadows;
}
.element {
@include box-shadow(
0 2px 4px rgba(0, 0, 0, 0.1),
0 4px 8px rgba(0, 0, 0, 0.1)
);
}
// 编译后
.element {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.1);
}
@content 内容块 #
@content 允许向混合宏传递样式块:
scss
@mixin media($breakpoint) {
@media (min-width: $breakpoint) {
@content;
}
}
.container {
width: 100%;
@include media(768px) {
width: 750px;
}
@include media(1024px) {
width: 960px;
}
}
// 编译后
.container {
width: 100%;
}
@media (min-width: 768px) {
.container {
width: 750px;
}
}
@media (min-width: 1024px) {
.container {
width: 960px;
}
}
响应式断点 #
scss
$breakpoints: (
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px
);
@mixin respond-to($key) {
$breakpoint: map-get($breakpoints, $key);
@if $breakpoint {
@media (min-width: $breakpoint) {
@content;
}
}
}
.element {
padding: 10px;
@include respond-to(md) {
padding: 20px;
}
@include respond-to(lg) {
padding: 30px;
}
}
伪元素和伪类 #
scss
@mixin pseudo($display: block, $content: '') {
content: $content;
display: $display;
}
.element {
position: relative;
&::before {
@include pseudo;
position: absolute;
top: 0;
left: 0;
}
&::after {
@include pseudo(inline-block, '→');
}
}
实用混合宏示例 #
Flexbox 布局 #
scss
@mixin flex($direction: row, $justify: flex-start, $align: stretch) {
display: flex;
flex-direction: $direction;
justify-content: $justify;
align-items: $align;
}
@mixin flex-center {
@include flex(row, center, center);
}
@mixin flex-between {
@include flex(row, space-between, center);
}
@mixin flex-column {
@include flex(column);
}
.container {
@include flex-center;
}
.header {
@include flex-between;
}
.sidebar {
@include flex-column;
}
绝对定位 #
scss
@mixin absolute($top: null, $right: null, $bottom: null, $left: null) {
position: absolute;
top: $top;
right: $right;
bottom: $bottom;
left: $left;
}
@mixin absolute-center {
@include absolute(50%, null, null, 50%);
transform: translate(-50%, -50%);
}
@mixin absolute-fill {
@include absolute(0, 0, 0, 0);
}
.modal-overlay {
@include absolute-fill;
background-color: rgba(0, 0, 0, 0.5);
}
.modal-content {
@include absolute-center;
background-color: white;
}
文本截断 #
scss
@mixin truncate($lines: 1) {
@if $lines == 1 {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
} @else {
display: -webkit-box;
-webkit-line-clamp: $lines;
-webkit-box-orient: vertical;
overflow: hidden;
}
}
.title {
@include truncate; // 单行截断
}
.description {
@include truncate(3); // 三行截断
}
按钮变体 #
scss
@mixin button-variant($background, $color: white, $hover-darken: 10%) {
background-color: $background;
color: $color;
&:hover {
background-color: darken($background, $hover-darken);
}
&:active {
background-color: darken($background, $hover-darken + 5%);
}
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
}
.btn-primary {
@include button-variant(#3498db);
}
.btn-danger {
@include button-variant(#e74c3c);
}
.btn-success {
@include button-variant(#2ecc71);
}
渐变背景 #
scss
@mixin gradient($direction, $colors...) {
background: linear-gradient($direction, $colors);
}
@mixin gradient-x($colors...) {
@include gradient(to right, $colors...);
}
@mixin gradient-y($colors...) {
@include gradient(to bottom, $colors...);
}
.header {
@include gradient-y(#3498db, #2980b9);
}
.banner {
@include gradient(45deg, #e74c3c, #9b59b6);
}
过渡动画 #
scss
@mixin transition($properties...) {
transition-property: $properties;
transition-duration: 0.3s;
transition-timing-function: ease;
}
@mixin transition-all($duration: 0.3s) {
transition: all $duration ease;
}
.button {
@include transition(background-color, color);
&:hover {
background-color: darken(#3498db, 10%);
}
}
.card {
@include transition-all(0.2s);
&:hover {
transform: translateY(-5px);
}
}
清除浮动 #
scss
@mixin clearfix {
&::after {
content: '';
display: table;
clear: both;
}
}
.container {
@include clearfix;
.left {
float: left;
}
.right {
float: right;
}
}
隐藏元素 #
scss
@mixin hidden {
display: none !important;
}
@mixin visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.hidden {
@include hidden;
}
.sr-only {
@include visually-hidden;
}
高级技巧 #
条件判断 #
scss
@mixin button($size: medium) {
padding: if($size == small, 5px 10px,
if($size == medium, 10px 20px,
if($size == large, 15px 30px, 10px 20px)));
}
.btn-sm { @include button(small); }
.btn-md { @include button(medium); }
.btn-lg { @include button(large); }
循环生成类 #
scss
@mixin generate-spacing-classes($sizes) {
@each $name, $value in $sizes {
.mt-#{$name} { margin-top: $value; }
.mb-#{$name} { margin-bottom: $value; }
.ml-#{$name} { margin-left: $value; }
.mr-#{$name} { margin-right: $value; }
}
}
$spacing: (
sm: 8px,
md: 16px,
lg: 24px
);
@include generate-spacing-classes($spacing);
使用映射参数 #
scss
@mixin button-styles($options: ()) {
$defaults: (
padding: 10px 20px,
radius: 4px,
color: white
);
$config: map-merge($defaults, $options);
padding: map-get($config, padding);
border-radius: map-get($config, radius);
color: map-get($config, color);
}
.button {
@include button-styles((
padding: 15px 30px,
radius: 8px
));
}
最佳实践 #
1. 单一职责 #
scss
// 好:职责单一
@mixin truncate {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
// 不好:职责过多
@mixin text-styles {
font-size: 16px;
color: #333;
overflow: hidden;
text-overflow: ellipsis;
}
2. 合理的默认值 #
scss
// 好:提供合理的默认值
@mixin border-radius($radius: 4px) {
border-radius: $radius;
}
// 不好:无默认值,每次都要传参
@mixin border-radius($radius) {
border-radius: $radius;
}
3. 语义化命名 #
scss
// 好:语义清晰
@mixin flex-center { }
@mixin text-truncate { }
@mixin visually-hidden { }
// 不好:含义不明
@mixin fc { }
@mixin tt { }
@mixin vh { }
下一步 #
掌握了混合宏后,继续学习 自定义函数,创建更灵活的样式逻辑!
最后更新:2026-03-28