第四章:精通 SCSS 内置函数:你的超级工具箱

第四章:精通 SCSS 内置函数:你的超级工具箱

摘要: 如果说前面章节是学习 SCSS 的语法和结构,那么本章就是学习 SCSS 的“标准库”。我们将深入探索 SCSS 官方提供的、极其强大的内置函数模块 (sass:color, sass:map, sass:string, sass:math, sass:list)。您将学会如何像经验丰富的开发者一样,利用这些函数进行颜色操作、数据检索、字符串处理和数学计算,构建出更智能、更健壮、更具动态性的高级样式代码。


4.1. 颜色函数 (sass:color):动态色彩魔法

颜色函数是 SCSS 中最常用、最强大的工具之一,它让我们能以编程的方式去操作、混合和调整颜色。

痛点背景: 当我们需要一个按钮的 hover 状态比它的基础色深一点,或者需要一个半透明的遮罩层颜色时,常常需要手动去颜色选择器里取一个新的色值。这种方式不仅效率低下,而且当主色调改变时,所有衍生的颜色都需要手动更新,极易出错。

解决方案: 使用颜色函数动态计算出衍生颜色。当然!您说得非常对,sass:color 模块的功能远不止那四个核心函数。下面我为您整理了一份更详尽、更实用的常用颜色函数列表,并按照功能进行了分类,包含了清晰的描述和直观的示例。

小提示: 现代 Sass 推荐使用 color.adjust()color.scale(),因为它们功能更强大、逻辑更一致。而像 lighten()darken() 这类传统函数依然被广泛使用,可以看作是 color.adjust() 的便捷版本。

函数描述
核心调整函数
color.adjust($color, ...)全能微调器。通过增加或减少一个绝对值来调整颜色的一个或多个通道($red, $green, $blue, $hue, $saturation, $lightness, $alpha)。
color.scale($color, ...)智能缩放器。按百分比缩放颜色属性,使其更接近该属性的最大值或最小值。尤其适合处理亮度和饱和度,效果比 lighten/darken 更自然。
color.change($color, ...)精确替换器。直接用新值替换颜色一个或多个通道的值。最常用于设置一个精确的透明度。
color.mix($c1, $c2, $weight: 50%)调色盘。将两种颜色按给定的权重进行混合。权重决定了第一种颜色的比例。
便捷函数 (传统函数)
lighten($color, $amount)增亮。增加颜色的亮度。是 color.adjust($color, $lightness: $amount) 的简写。
darken($color, $amount)变暗。减少颜色的亮度。是 color.adjust($color, $lightness: -$amount) 的简写。
saturate($color, $amount)增饱和。增加颜色的饱和度。是 color.adjust($color, $saturation: $amount) 的简写。
desaturate($color, $amount)降饱和。减少颜色的饱和度。是 color.adjust($color, $saturation: -$amount) 的简写。
grayscale($color)转为灰度。完全移除颜色的饱和度。是 desaturate($color, 100%) 的简写。
opacify($color, $amount)增不透明。增加颜色的不透明度(alpha 值)。是 color.adjust($color, $alpha: $amount) 的简写。
transparentize($color, $amount)增透明。增加颜色的透明度(即减少 alpha 值)。是 color.adjust($color, $alpha: -$amount) 的简写。
invert($color, $weight: 100%)反相。将颜色反相(像照片底片一样)。可以控制反相的权重。
complement($color)取补色。返回色轮上 180 度相对的颜色。是 adjust-hue($color, 180deg) 的简写。

颜色函数实战:创建一个动态的主题按钮

我们将创建一个 .btn-theme,它的 hover 状态、active 状态以及 disabled 状态的颜色,都由一个基础主题色 $theme-color 动态生成。

文件路径: scss/components/_theme_button.scss (新增)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@use "sass:color";

// 定义一个基础主题色
$theme-color: #27ea00; // 蓝色

.btn-theme {
padding: 10px 20px;
border: none;
border-radius: 5px;
color: white; // 初始文本颜色
cursor: pointer;
transition: background-color 0.2s ease-in-out;

// 基础状态
background-color: $theme-color;

// Hover 状态:使用 scale 降低 10% 的亮度
&:hover {
background-color: color.scale($theme-color, $lightness: -10%);
}

// Active (点击) 状态:使用 scale 降低 20% 的亮度
&:active {
transform: scale(0.98);
background-color: color.scale($theme-color, $lightness: -20%);
}

// Disabled 状态:使用 change 改变透明度为 50%
&:disabled {
background-color: color.change($theme-color, $alpha: 0.5);
cursor: not-allowed;
}
}

文件路径: scss/main.scss (添加导入)

1
2
// ...
@use 'components/theme_button';

文件路径: index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>SCSS 颜色函数实战</title>
<link rel="stylesheet" href="scss/main.css">
<style> body { padding: 20px; } button { margin-right: 10px; } </style>
</head>
<body>
<h2>颜色函数动态生成的按钮状态</h2>
<p>所有颜色都由一个 <code>$theme-color</code> 变量计算而来。</p>
<button class="btn-theme">基础状态</button>
<button class="btn-theme" disabled>禁用状态</button>
</body>
</html>

4.2. Map 函数 (sass:map):你的设计数据中心

Map 函数是操作 Map 数据结构的核心工具,能让你安全、高效地存取设计令牌。

核心思想: Sass 中的 Map 是不可变 (immutable) 的。这意味着像 map.setmap.remove 这样的函数并不会修改原始 Map,而是返回一个修改后的新 Map

痛点背景: 在大型项目中,直接访问 Map 中的值(如 map.get)如果 key 不存在,会返回 null,这可能导致编译错误或非预期的样式。我们需要一种更健壮的方式来获取数据。

解决方案: 结合 map.has-keymap.get 封装一个安全的函数,如果 key 不存在,就清晰地报错。

文件路径: scss/abstracts/_functions.scss (修改)

1
2
3
4
5
6
7
8
9
10
@use "sass:map";
@use "variables" as v;

// 一个安全获取主题颜色的函数
@function theme-color($key: "primary") {
@if not map.has-key(v.$theme-colors, $key) {
@error "颜色 '#{$key}' 在 $theme-colors 中不存在。";
}
@return map.get(v.$theme-colors, $key);
}

Map 函数实战:创建一组主题面板

我们将利用封装好的 theme-color 函数,创建一组背景和边框颜色都由 $theme-colors Map 驱动的面板组件。

文件路径: scss/components/_panel.scss (新增)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@use '../abstracts/functions' as f;
@use '../abstracts/mixins' as m;
@use 'sass:color';

.panel {
padding: 20px;
margin-bottom: 20px;
border-radius: 5px;
border: 2px solid;
}

// 遍历主题色 Map 来创建所有面板的变体
@each $color-name, $color-value in f.v.$theme-colors {
.panel-#{$color-name} {
// 使用函数安全地获取颜色
$bg-color: f.theme-color($color-name);

// 背景色使用原色,并调整透明度
background-color: color.change($bg-color, $alpha: 0.1);
// 边框使用原色
border-color: $bg-color;
// 文本颜色也使用原色
color: $bg-color;
}
}

文件路径: scss/main.scss (添加导入)

1
2
// ...
@use 'components/panel';

文件路径: index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>SCSS Map 函数实战</title>
<link rel="stylesheet" href="scss/main.css">
<style> body { padding: 20px; max-width: 600px; margin: auto; } </style>
</head>
<body>
<h2>Map 函数驱动的主题面板</h2>
<div class="panel panel-primary">
<h3>Primary Panel</h3>
<p>这个面板的背景、边框和文本颜色都来自于 <code>theme-color("primary")</code></p>
</div>
<div class="panel panel-danger">
<h3>Danger Panel</h3>
<p>这个面板的背景、边框和文本颜色都来自于 <code>theme-color("danger")</code></p>
</div>
</body>
</html>

4.3. 数学函数 (sass:math):精确的动态计算

sass:math 模块是 SCSS 进行动态计算的基石。它不仅提供了基础的算术运算,还包含了单位处理、取整、比较等一系列强大的功能,能让你在编译阶段就完成复杂的布局和尺寸计算。

最重要的变化: 在现代 Dart Sass 中,/ 符号默认被用作 CSS 的分隔符(例如 font: 16px / 1.5;)。因此,所有除法运算必须使用 math.div() 函数来完成,否则会收到弃用警告或编译错误。

常用 sass:math 函数详解

函数描述
核心与单位函数
math.div($n1, $n2)安全除法。执行数字除法运算,是替代 / 的标准方式。
math.unit($number)获取单位。返回一个数字的单位作为字符串。
math.unitless($number)检查单位。检查一个数字是否带有单位,返回 truefalse
math.compatible($n1, $n2)单位兼容性检查。检查两个数字的单位是否可以互相转换和运算。
取整与舍入函数
math.round($number)四舍五入。将数字舍入到最接近的整数。
math.ceil($number)向上取整。将数字舍入到下一个更大的整数。
math.floor($number)向下取整。将数字舍入到下一个更小的整数。
math.abs($number)取绝对值。返回数字的非负值。
比较与极值函数
math.min($n1, $n2, ...)取最小值。从一系列数字中返回最小的一个。
math.max($n1, $n2, ...)取最大值。从一系列数字中返回最大的一个。
高级与特殊函数
math.random($limit: null)生成随机数。不带参数时返回 0 到 1 之间的小数;带整数参数 $limit 时返回 1 到 $limit 之间的随机整数。
math.pow($base, $exponent)幂运算。计算一个数的幂。常用于创建和谐的字体或间距比例。
math.sqrt($number)平方根。计算一个数的平方根。