应使用 $font-stacks Map 定义语义化字体堆栈,key 用带引号字符串(如 "sans"),value 中中文字体名必须双引号包裹(如 "PingFang SC"),再通过带校验的 font-stack() 函数安全调用,避免 null 值和拼写错误。

为什么不能用单变量存字体族
直接写 $font-sans 这类变量,项目一复杂就崩:中英文混排时中文要 "PingFang SC",西文得 fallback 到 Arial,单变量没法区分;新增一个 code-font 类型,就得手动改遍所有 pre、kbd、code 选择器;更麻烦的是,某些组件需要 font-weight: 500 的 sans 堆栈,其他地方是 normal,单变量塞不进参数;编译后全是重复长字符串,gzip 压缩率低,DevTools 里也难定位来源。
怎么用 $font-stacks Map 定义语义化字体堆栈
把“用途 + 字体顺序”打包成 Map 条目,key 必须是带引号的字符串,value 是逗号分隔的字体字符串(中文字体名带空格必须双引号包裹):
$font-stacks: ( "sans": '"PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Helvetica, Arial, sans-serif', "serif": '"Georgia", "Times New Roman", Times, serif', "mono": '"Fira Code", "Consolas", "Courier New", monospace', "chinese-ui": '"SF Pro SC", "PingFang SC", sans-serif' );
-
"sans"这种 key 不加引号会报错Undefined variable "sans" - 值里
"PingFang SC"的双引号不能省,否则 Sass 解析成两个词PingFang和SC - 避免嵌套 Map,比如
"light": ("sans": "..."),徒增map-get(map-get(...))链式调用
如何安全调用 font-stack() 函数提取字体
别裸用 map-get($font-stacks, "sans") —— 拼错 key 或键不存在时返回 null,导致 font-family: null,浏览器忽略整条声明,肉眼难发现。封装一层带校验的函数更稳妥:
@function font-stack($key, $fallback: sans-serif) {
@if map-has-key($font-stacks, $key) {
@return map-get($font-stacks, $key);
}
@warn "Unknown font stack '#{$key}' — using fallback";
@return $fallback;
}
- 调用写
font-family: font-stack("chinese-ui"),比硬编码或裸map-get更健壮 -
$fallback参数留着应对临时需求,比如某组件需降级到system-ui - 函数内用
map-has-key()预检,避免运行时静默失效
生成 CSS 自定义属性时注意作用域和命名对齐
想把字体堆栈转成 :root 下的 CSS 变量供 JS 读取,必须确保 @each 循环在顶层(不在任何选择器或 @media 块内),否则变量只在局部生效:
立即学习“前端免费学习笔记(深入)”;
@each $name, $value in $font-stacks {
--font-#{$name}: #{$value};
}
- 生成的变量名是
--font-sans,JS 侧读取时得严格匹配,拼成--font-Sans就失效 - 如果项目用 JS 动态切换字体(如用户偏好设置),Sass 层只提供源数据,真正生效靠
document.documentElement.style.setProperty('--font-sans', '...') - Map 本身不支持运行时更新,所谓“动态换肤”本质是预编译多套 CSS 或靠 CSS 变量 + JS 控制
真正容易被忽略的是:字体堆栈里单位、引号、空格的组合极容易在插值时出错,比如误写 #{map-get($font-stacks, sans)}(漏引号)或 "#{$value}"(多套引号),结果输出非法 CSS;每次修改 Map 后,务必检查生成的 CSS 是否含完整双引号包裹的中文字体名。


















