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