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