Sass 自定义函数 #

什么是函数? #

Sass 函数与混合宏类似,但函数返回一个值而不是输出样式。函数可以用于计算、转换数据等场景。

scss
// 定义函数
@function double($value) {
  @return $value * 2;
}

// 使用函数
.container {
  width: double(100px);  // 200px
}

基本语法 #

定义函数 #

scss
@function function-name($param1, $param2, ...) {
  // 逻辑代码
  @return value;
}

调用函数 #

scss
selector {
  property: function-name(arg1, arg2);
}

函数 vs 混合宏 #

特性 函数 混合宏
返回值 返回一个值 输出样式块
使用方式 作为属性值 使用 @include
用途 计算、转换 生成样式
scss
// 混合宏:输出样式
@mixin center {
  display: flex;
  justify-content: center;
  align-items: center;
}

// 函数:返回值
@function calculate-width($columns) {
  @return $columns * 100px;
}

.container {
  @include center;  // 使用混合宏
  width: calculate-width(3);  // 使用函数
}

基础函数示例 #

数学计算 #

scss
@function double($value) {
  @return $value * 2;
}

@function half($value) {
  @return $value / 2;
}

@function percentage($value, $total) {
  @return ($value / $total) * 100%;
}

.element {
  width: double(50px);        // 100px
  padding: half(20px);        // 10px
  flex-basis: percentage(3, 12);  // 25%
}

单位转换 #

scss
$base-font-size: 16px;

@function px-to-rem($px) {
  @return ($px / $base-font-size) * 1rem;
}

@function rem-to-px($rem) {
  @return ($rem * $base-font-size);
}

.text {
  font-size: px-to-rem(24px);  // 1.5rem
  margin: px-to-rem(16px);     // 1rem
}

颜色处理 #

scss
@function tint($color, $percentage) {
  @return mix(white, $color, $percentage);
}

@function shade($color, $percentage) {
  @return mix(black, $color, $percentage);
}

$primary: #3498db;

.button {
  background-color: $primary;
  
  &:hover {
    background-color: tint($primary, 20%);  // 变亮
  }
  
  &:active {
    background-color: shade($primary, 20%);  // 变暗
  }
}

参数特性 #

默认参数 #

scss
@function spacing($multiplier: 1) {
  @return $multiplier * 8px;
}

.element {
  padding: spacing();    // 8px
  margin: spacing(2);    // 16px
  gap: spacing(3);       // 24px
}

关键字参数 #

scss
@function color-alpha($color, $alpha: 1) {
  @return rgba($color, $alpha);
}

.element {
  background-color: color-alpha(#3498db, 0.5);
  border-color: color-alpha(#3498db, $alpha: 0.3);
}

可变参数 #

scss
@function sum($numbers...) {
  $total: 0;
  @each $number in $numbers {
    $total: $total + $number;
  }
  @return $total;
}

.element {
  width: sum(10px, 20px, 30px);  // 60px
}

实用函数示例 #

获取映射值 #

scss
$colors: (
  primary: #3498db,
  secondary: #2ecc71,
  danger: #e74c3c,
  warning: #f39c12
);

@function color($key) {
  @return map-get($colors, $key);
}

@function color-level($key, $level: 0) {
  $color: map-get($colors, $key);
  @if $level > 0 {
    @return lighten($color, $level * 10%);
  } @else if $level < 0 {
    @return darken($color, abs($level) * 10%);
  }
  @return $color;
}

.button {
  background-color: color(primary);
}

.button-light {
  background-color: color-level(primary, 1);  // 变亮
}

.button-dark {
  background-color: color-level(primary, -1);  // 变暗
}

响应式字体 #

scss
@function fluid-font-size($min, $max, $min-vw: 320px, $max-vw: 1200px) {
  @return clamp(
    $min,
    calc(#{$min} + #{strip-unit($max - $min)} * ((100vw - #{$min-vw}) / #{strip-unit($max-vw - $min-vw)})),
    $max
  );
}

@function strip-unit($value) {
  @return $value / ($value * 0 + 1);
}

.title {
  font-size: fluid-font-size(16px, 32px);
}

网格计算 #

scss
$grid-columns: 12;
$grid-gutter: 30px;

@function grid-column($columns) {
  @return percentage($columns / $grid-columns);
}

@function grid-offset($columns) {
  @return percentage($columns / $grid-columns);
}

@function grid-push($columns) {
  @return percentage($columns / $grid-columns);
}

.col-6 {
  width: grid-column(6);  // 50%
}

.col-offset-2 {
  margin-left: grid-offset(2);  // 16.666%
}

Z-index 管理 #

scss
$z-layers: (
  modal: 1000,
  overlay: 900,
  dropdown: 800,
  header: 100,
  footer: 50,
  default: 1
);

@function z($layer) {
  @return map-get($z-layers, $layer);
}

.modal {
  z-index: z(modal);  // 1000
}

.overlay {
  z-index: z(overlay);  // 900
}

.dropdown {
  z-index: z(dropdown);  // 800
}

间距系统 #

scss
$spacer: 1rem;
$spacers: (
  0: 0,
  1: $spacer * 0.25,
  2: $spacer * 0.5,
  3: $spacer,
  4: $spacer * 1.5,
  5: $spacer * 3
);

@function spacer($level: 3) {
  @return map-get($spacers, $level);
}

.section {
  padding: spacer(4);
  margin-bottom: spacer(3);
}

字体大小 #

scss
$font-sizes: (
  xs: 0.75rem,
  sm: 0.875rem,
  base: 1rem,
  lg: 1.125rem,
  xl: 1.25rem,
  2xl: 1.5rem,
  3xl: 1.875rem,
  4xl: 2.25rem
);

@function font-size($size: base) {
  @return map-get($font-sizes, $size);
}

.text-sm {
  font-size: font-size(sm);
}

.text-lg {
  font-size: font-size(lg);
}

断点获取 #

scss
$breakpoints: (
  xs: 0,
  sm: 576px,
  md: 768px,
  lg: 992px,
  xl: 1200px,
  xxl: 1400px
);

@function breakpoint($name) {
  @return map-get($breakpoints, $name);
}

@mixin media-up($name) {
  @media (min-width: breakpoint($name)) {
    @content;
  }
}

.container {
  @include media-up(md) {
    width: 750px;
  }
}

内置函数 #

颜色函数 #

scss
$color: #3498db;

.element {
  // 调整亮度
  color: lighten($color, 20%);
  color: darken($color, 20%);
  
  // 调整饱和度
  color: saturate($color, 20%);
  color: desaturate($color, 20%);
  
  // 调整透明度
  color: rgba($color, 0.5);
  color: opacify($color, 0.3);
  color: transparentize($color, 0.3);
  
  // 混合颜色
  color: mix(red, blue, 50%);
  
  // 获取颜色分量
  red-value: red($color);
  green-value: green($color);
  blue-value: blue($color);
  hue-value: hue($color);
  saturation-value: saturation($color);
  lightness-value: lightness($color);
}

字符串函数 #

scss
$string: "Hello World";

.element {
  // 大小写转换
  content: to-upper-case($string);  // "HELLO WORLD"
  content: to-lower-case($string);  // "hello world"
  
  // 字符串长度
  length: str-length($string);  // 11
  
  // 查找和替换
  content: str-index($string, "World");  // 7
  content: str-insert($string, "!", 12);  // "Hello World!"
  content: str-slice($string, 1, 5);  // "Hello"
}

列表函数 #

scss
$list: 10px, 20px, 30px;

.element {
  // 获取长度
  length: length($list);  // 3
  
  // 获取元素
  first: nth($list, 1);  // 10px
  last: nth($list, -1);  // 30px
  
  // 添加元素
  new-list: append($list, 40px);  // 10px, 20px, 30px, 40px
  
  // 查找索引
  index: index($list, 20px);  // 2
}

映射函数 #

scss
$map: (
  primary: #3498db,
  secondary: #2ecc71
);

.element {
  // 获取值
  color: map-get($map, primary);  // #3498db
  
  // 合并映射
  $merged: map-merge($map, (danger: #e74c3c));
  
  // 获取键列表
  $keys: map-keys($map);  // primary, secondary
  
  // 获取值列表
  $values: map-values($map);  // #3498db, #2ecc71
  
  // 检查键是否存在
  $has-key: map-has-key($map, primary);  // true
}

数学函数 #

scss
.element {
  // 基本运算
  width: 10px + 20px;  // 30px
  width: 100px - 20px;  // 80px
  width: 10px * 2;  // 20px
  width: 100px / 2;  // 50px
  
  // 取整
  value: round(4.6);  // 5
  value: ceil(4.2);   // 5
  value: floor(4.8);  // 4
  
  // 绝对值
  value: abs(-10);  // 10
  
  // 最大最小值
  value: max(10, 20, 30);  // 30
  value: min(10, 20, 30);  // 10
  
  // 随机数
  value: random(100);  // 1-100 随机数
}

高级函数 #

递归函数 #

scss
@function factorial($n) {
  @if $n <= 1 {
    @return 1;
  }
  @return $n * factorial($n - 1);
}

.element {
  value: factorial(5);  // 120
}

条件函数 #

scss
@function get-color($theme, $type) {
  $themes: (
    light: (
      bg: white,
      text: black
    ),
    dark: (
      bg: black,
      text: white
    )
  );
  
  $theme-map: map-get($themes, $theme);
  @return map-get($theme-map, $type);
}

body {
  background-color: get-color(light, bg);
  color: get-color(light, text);
}

最佳实践 #

1. 单一职责 #

scss
// 好:职责单一
@function px-to-rem($px) {
  @return ($px / 16px) * 1rem;
}

// 不好:职责过多
@function convert($value, $to-unit) {
  // 处理多种转换
}

2. 提供默认值 #

scss
// 好:有默认值
@function spacer($level: 3) {
  @return map-get($spacers, $level);
}

// 不好:无默认值
@function spacer($level) {
  @return map-get($spacers, $level);
}

3. 错误处理 #

scss
@function get-color($name) {
  @if not map-has-key($colors, $name) {
    @error "Color '#{$name}' not found in $colors map";
  }
  @return map-get($colors, $name);
}

下一步 #

掌握了自定义函数后,继续学习 控制指令,实现更复杂的逻辑控制!

最后更新:2026-03-28