函数(Functions)
2025年3月5日大约 11 分钟
SCSS/SASS函数(Functions)
函数的概念与意义
函数是Sass中的强大特性,它允许你定义可重用的计算逻辑,接受输入参数并返回计算结果。Sass函数类似于编程语言中的函数,可以执行各种操作,如颜色转换、数学计算、字符串处理等。
函数的主要优势:
- 代码复用:将常用计算逻辑封装为函数
- 提高可维护性:集中管理复杂计算
- 增强可读性:使用语义化函数名代替复杂表达式
- 减少错误:一次编写,多处使用
内置函数
Sass提供了丰富的内置函数,以下是一些常用的函数示例:
颜色函数
Sass提供了强大的颜色处理函数,可以进行各种颜色操作:
.button {
// 基本颜色函数
background-color: rgb(0, 123, 255); // RGB颜色
color: lighten(#000, 80%); // 变亮
border-color: darken(#007bff, 10%); // 变暗
// 高级颜色操作
&:hover {
background-color: mix(#007bff, #000, 85%); // 混合颜色
box-shadow: rgba(#007bff, 0.5); // 透明度调整
}
// 色相调整
&:active {
background-color: adjust-hue(#007bff, 15deg); // 调整色相
border-color: saturate(#007bff, 20%); // 增加饱和度
}
// 颜色提取
$text-color: complement(#007bff); // 互补色
color: $text-color;
}
常用颜色函数列表
函数 | 描述 | 示例 |
---|---|---|
rgb(r, g, b) | 创建RGB颜色 | rgb(255, 0, 0) |
rgba(r, g, b, a) | 创建带透明度的RGB颜色 | rgba(255, 0, 0, 0.5) |
hsl(h, s, l) | 创建HSL颜色 | hsl(0, 100%, 50%) |
lighten(color, amount) | 使颜色变亮 | lighten(#007bff, 20%) |
darken(color, amount) | 使颜色变暗 | darken(#007bff, 20%) |
saturate(color, amount) | 增加饱和度 | saturate(#007bff, 20%) |
desaturate(color, amount) | 减少饱和度 | desaturate(#007bff, 20%) |
adjust-hue(color, degrees) | 调整色相 | adjust-hue(#007bff, 30deg) |
mix(color1, color2, weight) | 混合两种颜色 | mix(#007bff, #000, 70%) |
complement(color) | 获取互补色 | complement(#007bff) |
invert(color) | 获取反色 | invert(#007bff) |
grayscale(color) | 转换为灰度 | grayscale(#007bff) |
数值函数
Sass提供了多种数值处理函数,用于执行数学运算和单位转换:
.element {
// 基本数值函数
width: percentage(0.8); // 转换为百分比:80%
height: round(3.7px); // 四舍五入:4px
margin: abs(-15px); // 绝对值:15px
padding: min(10px, 20px); // 最小值:10px
// 高级数值操作
$base-size: 16px;
font-size: ceil($base-size * 1.2); // 向上取整:20px
line-height: floor($base-size * 1.5); // 向下取整:24px
// 单位转换
$width-px: 500px;
width: $width-px / 16px * 1rem; // 转换为rem:31.25rem
// 随机数
z-index: random(100); // 1到100之间的随机数
}
常用数值函数列表
函数 | 描述 | 示例 |
---|---|---|
percentage(number) | 转换为百分比 | percentage(0.85) → 85% |
round(number) | 四舍五入 | round(3.7) → 4 |
ceil(number) | 向上取整 | ceil(3.2) → 4 |
floor(number) | 向下取整 | floor(3.8) → 3 |
abs(number) | 绝对值 | abs(-15) → 15 |
min(numbers...) | 最小值 | min(10px, 20px, 5px) → 5px |
max(numbers...) | 最大值 | max(10px, 20px, 5px) → 20px |
random(limit) | 随机数 | random(100) → 42 (随机值) |
字符串函数
Sass提供了多种字符串处理函数,用于操作和格式化字符串:
$path: "assets/images";
$file: "logo.png";
.logo {
// 基本字符串函数
background: url(#{$path}/#{to-upper-case($file)}); // 转大写
content: quote("Hello world"); // 添加引号:"Hello world"
// 字符串操作
$name: "button";
$modifier: "primary";
class: unquote(".#{$name}--#{$modifier}"); // 移除引号:.button--primary
// 字符串提取
$full-path: "assets/images/logo.png";
content: str-slice($full-path, 8, 14); // 提取子字符串:images
// 字符串替换
$class-name: "btn-default";
content: str-replace($class-name, "default", "primary"); // btn-primary
}
常用字符串函数列表
函数 | 描述 | 示例 |
---|---|---|
to-upper-case(string) | 转换为大写 | to-upper-case("hello") → "HELLO" |
to-lower-case(string) | 转换为小写 | to-lower-case("HELLO") → "hello" |
str-length(string) | 字符串长度 | str-length("hello") → 5 |
str-slice(string, start, end) | 提取子字符串 | str-slice("hello", 2, 4) → "ell" |
quote(string) | 添加引号 | quote(hello) → "hello" |
unquote(string) | 移除引号 | unquote("hello") → hello |
列表函数
Sass提供了处理列表的函数,用于操作数组类型的数据:
$colors: red, green, blue;
$sizes: 10px 20px 30px;
.element {
// 列表访问
color: nth($colors, 2); // 获取第二项:green
// 列表操作
$updated-colors: append($colors, yellow); // 添加项:red, green, blue, yellow
background-color: nth($updated-colors, 4); // yellow
// 列表信息
$list-length: length($sizes); // 列表长度:3
width: nth($sizes, $list-length); // 获取最后一项:30px
// 列表转换
$comma-list: join($colors, $sizes, comma); // 合并列表:red, green, blue, 10px, 20px, 30px
content: inspect($comma-list);
}
常用列表函数列表
函数 | 描述 | 示例 |
---|---|---|
length(list) | 列表长度 | length(10px 20px 30px) → 3 |
nth(list, n) | 获取第n项 | nth(10px 20px 30px, 2) → 20px |
index(list, value) | 查找值的索引 | index(10px 20px 30px, 20px) → 2 |
append(list, value) | 添加值到列表末尾 | append(10px 20px, 30px) → 10px 20px 30px |
join(list1, list2) | 合并两个列表 | join(10px 20px, 30px 40px) → 10px 20px 30px 40px |
zip(lists...) | 将多个列表交错组合 | zip(1px 2px, solid dashed, red blue) → 1px solid red, 2px dashed blue |
Map函数
Sass中的Map是键值对集合,类似于其他编程语言中的字典或对象:
$theme-colors: (
"primary": #007bff,
"secondary": #6c757d,
"success": #28a745,
"danger": #dc3545
);
.alert {
// 获取Map值
background-color: map-get($theme-colors, "success"); // #28a745
// Map操作
$updated-colors: map-merge($theme-colors, ("warning": #ffc107)); // 添加新键值对
border-color: map-get($updated-colors, "warning"); // #ffc107
// Map信息
$has-key: map-has-key($theme-colors, "info"); // 检查键是否存在:false
// 遍历Map
@each $name, $color in $theme-colors {
&--#{$name} {
background-color: $color;
color: if(lightness($color) > 50%, #000, #fff);
}
}
}
常用Map函数列表
函数 | 描述 | 示例 |
---|---|---|
map-get(map, key) | 获取指定键的值 | map-get(("a": 1, "b": 2), "a") → 1 |
map-has-key(map, key) | 检查键是否存在 | map-has-key(("a": 1), "b") → false |
map-keys(map) | 获取所有键的列表 | map-keys(("a": 1, "b": 2)) → "a", "b" |
map-values(map) | 获取所有值的列表 | map-values(("a": 1, "b": 2)) → 1, 2 |
map-merge(map1, map2) | 合并两个Map | map-merge(("a": 1), ("b": 2)) → ("a": 1, "b": 2) |
map-remove(map, keys...) | 移除指定键 | map-remove(("a": 1, "b": 2), "a") → ("b": 2) |
自定义函数
除了使用内置函数,Sass还允许你创建自定义函数来满足特定需求。
基本语法
自定义函数使用@function
指令定义,使用@return
返回结果:
// 自定义函数
@function calculate-width($col-span, $total-cols: 12) {
@return percentage($col-span / $total-cols);
}
.sidebar {
width: calculate-width(3); // 25%
}
.main-content {
width: calculate-width(9); // 75%
}
// 带有多个参数的函数
@function spacing($multiplier, $base-unit: 8px) {
@return $multiplier * $base-unit;
}
.card {
padding: spacing(2); // 16px
margin-bottom: spacing(3); // 24px
}
高级用法
Sass函数支持多种高级特性,如可变参数、条件逻辑和递归:
// 递归函数
@function sum($numbers...) {
$sum: 0;
@each $number in $numbers {
$sum: $sum + $number;
}
@return $sum;
}
// 条件函数
@function contrast-color($color) {
$lightness: lightness($color);
@return if($lightness > 50%, #000, #fff);
}
// 递归函数示例
@function fibonacci($n) {
@if $n <= 1 {
@return $n;
}
@return fibonacci($n - 1) + fibonacci($n - 2);
}
.dynamic-text {
background-color: #007bff;
color: contrast-color(#007bff); // 白色文本,因为背景较深
padding: sum(5px, 10px, 15px); // 30px
margin-bottom: fibonacci(5) * 1px; // 5px (fibonacci(5) = 5)
}
// 使用列表处理的函数
@function list-sum($list) {
$sum: 0;
@each $item in $list {
$sum: $sum + $item;
}
@return $sum;
}
$sizes: 10px, 20px, 30px;
.element {
padding: list-sum($sizes); // 60px
}
函数与混入的区别
Sass中的函数和混入都是代码复用机制,但它们有明显的区别:
特性 | 函数 (@function) | 混入 (@mixin) |
---|---|---|
主要目的 | 计算并返回值 | 生成CSS规则 |
使用方式 | 在属性值中使用 | 作为独立指令使用 |
返回值 | 必须返回一个值 | 不返回值,直接生成CSS |
调用语法 | property: function-name(args); | @include mixin-name(args); |
适用场景 | 值的计算和转换 | 生成重复的CSS规则 |
示例对比
// 函数:计算值
@function calculate-width($cols) {
@return $cols * 8.33333%;
}
// 混入:生成CSS规则
@mixin set-width($cols) {
width: $cols * 8.33333%;
}
.element-1 {
// 使用函数
width: calculate-width(6); // 返回值: 50%
}
.element-2 {
// 使用混入
@include set-width(6); // 生成: width: 50%;
}
实际应用案例
1. 响应式断点管理
// 断点Map
$breakpoints: (
"small": 576px,
"medium": 768px,
"large": 992px,
"xlarge": 1200px
);
// 获取断点值的函数
@function breakpoint($name) {
@if map-has-key($breakpoints, $name) {
@return map-get($breakpoints, $name);
} @else {
@error "未知的断点名称: #{$name}";
@return null;
}
}
// 使用断点函数
.container {
max-width: 100%;
@media (min-width: breakpoint("medium")) {
max-width: 720px;
}
@media (min-width: breakpoint("large")) {
max-width: 960px;
}
@media (min-width: breakpoint("xlarge")) {
max-width: 1140px;
}
}
2. 主题色系统
// 主题色Map
$theme-colors: (
"primary": #007bff,
"secondary": #6c757d,
"success": #28a745,
"danger": #dc3545,
"warning": #ffc107,
"info": #17a2b8
);
// 获取主题色的函数
@function theme-color($name) {
@return map-get($theme-colors, $name);
}
// 创建色彩变体的函数
@function theme-color-variant($name, $lightness: 0%) {
$color: theme-color($name);
@if $lightness > 0 {
@return lighten($color, $lightness);
} @else if $lightness < 0 {
@return darken($color, abs($lightness));
} @else {
@return $color;
}
}
// 使用主题色函数
.btn-primary {
background-color: theme-color("primary");
border-color: theme-color-variant("primary", -10%);
&:hover {
background-color: theme-color-variant("primary", -10%);
border-color: theme-color-variant("primary", -20%);
}
}
.alert-success {
background-color: theme-color-variant("success", 40%);
border-color: theme-color-variant("success", 30%);
color: theme-color-variant("success", -30%);
}
3. 排版比例系统
// 基础字体大小
$base-font-size: 16px;
// 类型比例函数
@function type-scale($level) {
$scale: 1.25; // 主要第三度音程比例
@if $level < 0 {
@return $base-font-size / pow($scale, abs($level));
} @else if $level > 0 {
@return $base-font-size * pow($scale, $level);
} @else {
@return $base-font-size;
}
}
// 幂函数
@function pow($base, $exponent) {
$result: 1;
@for $i from 1 through $exponent {
$result: $result * $base;
}
@return $result;
}
// 使用排版比例函数
h1 {
font-size: type-scale(4); // 约39.06px
}
h2 {
font-size: type-scale(3); // 约31.25px
}
h3 {
font-size: type-scale(2); // 约25px
}
h4 {
font-size: type-scale(1); // 约20px
}
body {
font-size: type-scale(0); // 16px (基础大小)
}
small {
font-size: type-scale(-1); // 约12.8px
}
最佳实践
多年的实践经验已经形成了一些关于Sass函数使用的最佳实践:
1. 函数命名规范
- 使用描述性的函数名,清晰表达函数的用途
- 遵循一致的命名约定,如使用连字符或驼峰命名法
- 避免与内置函数冲突,可以添加前缀区分
// 不推荐:名称不明确
@function c($n) {
@return $n * 8px;
}
// 推荐:描述性名称
@function spacing-unit($multiplier) {
@return $multiplier * 8px;
}
// 不推荐:与内置函数冲突
@function lighten($color, $amount) {
// 自定义实现...
}
// 推荐:添加前缀避免冲突
@function my-lighten($color, $amount) {
// 自定义实现...
}
2. 参数设计
- 为参数提供合理的默认值,增加函数的灵活性
- 使用清晰的参数名称,提高代码可读性
- 考虑使用可变参数处理不确定数量的输入
// 不推荐:没有默认值
@function grid-width($cols) {
@return $cols * 8.33333%;
}
// 推荐:提供默认值
@function grid-width($cols: 1, $total-cols: 12) {
@return percentage($cols / $total-cols);
}
// 不推荐:参数名称不清晰
@function m($a, $b: 10px) {
@return $a + $b;
}
// 推荐:清晰的参数名称
@function calculate-margin($base-size, $additional: 10px) {
@return $base-size + $additional;
}
// 推荐:使用可变参数
@function sum-values($values...) {
$sum: 0;
@each $value in $values {
$sum: $sum + $value;
}
@return $sum;
}
3. 错误处理
- 添加参数验证,确保函数接收有效输入
- 使用
@error
指令提供有用的错误信息 - 考虑使用
@warn
指令提供非致命警告
@function divide($a, $b) {
// 参数验证
@if type-of($a) != number {
@error "divide(): $a 必须是数字,得到 #{type-of($a)}";
}
@if type-of($b) != number {
@error "divide(): $b 必须是数字,得到 #{type-of($b)}";
}
// 除数为零检查
@if $b == 0 {
@error "divide(): 除数不能为零";
}
// 单位兼容性警告
@if unit($a) != unit($b) and unit($a) != "" and unit($b) != "" {
@warn "divide(): 单位可能不兼容: #{$a} 和 #{$b}";
}
@return $a / $b;
}
4. 文档化
- 为函数添加清晰的注释,说明其用途、参数和返回值
- 使用一致的注释格式,如SassDoc
- 提供使用示例,帮助其他开发者理解
/// 计算网格列宽
/// @param {Number} $cols - 列数
/// @param {Number} $total-cols [12] - 总列数
/// @return {Percentage} 列宽百分比
/// @example scss
/// .element {
/// width: grid-width(6); // 返回 50%
/// }
@function grid-width($cols, $total-cols: 12) {
@return percentage($cols / $total-cols);
}
5. 保持纯函数
- 函数应该是"纯"的,即对于相同的输入总是返回相同的输出
- 避免在函数内部修改全局变量或产生副作用
- 函数应专注于计算和返回值,而不是生成CSS规则
// 不推荐:函数有副作用
$global-counter: 0;
@function next-id() {
$global-counter: $global-counter + 1 !global;
@return $global-counter;
}
// 推荐:纯函数
@function calculate-id($base, $index) {
@return $base + $index;
}
总结
Sass函数是一个强大的工具,可以帮助你创建更加模块化、可维护和灵活的样式表。通过使用内置函数和创建自定义函数,你可以:
- 简化复杂计算:将复杂的计算逻辑封装为易于使用的函数
- 增强代码可读性:使用语义化的函数名代替复杂表达式
- 提高代码复用性:在多个地方使用相同的计算逻辑
- 创建一致的设计系统:通过函数确保颜色、间距和排版等设计元素的一致性
无论是处理颜色、执行数学运算、操作字符串还是管理复杂的设计系统,Sass函数都能提供强大的支持,是每个Sass开发者应该掌握的核心技能。
通过合理组合变量、函数、混入和其他Sass特性,你可以创建高度可配置、易于维护的CSS架构,显著提高前端开发的效率和质量。