用 $type-scales Map 定义字体层级结构排版样式,必须以嵌套 Map 表达 h1–h6 的 font-size、line-height、font-weight 三维度语义关系,避免单变量拆分;配合 @each 生成 .text-h1 等工具类,并通过断点 Map 和主题 Map 实现响应式与深色模式支持。

用 $type-scales Map 定义字体层级结构
排版样式不是靠一堆 $h1-font-size、$h2-line-height 单变量堆出来的——层级关系必须用 Map 表达。比如标题从 h1 到 h6,每个都该有 font-size、line-height、font-weight 三个维度,硬拆成六个变量会彻底失去语义关联。
正确写法是定义一个嵌套 Map:
$type-scales: (
"h1": (
"font-size": 2.5rem,
"line-height": 1.2,
"font-weight": 700
),
"h2": (
"font-size": 2rem,
"line-height": 1.3,
"font-weight": 600
)
);- 键名必须加引号(
"h1"),否则 Sass 把它当未定义变量报错 - 值必须是子 Map,不能是 list;否则
map-get($props, "font-size")会失败 - 避免在 Map 里写计算式如
font-size: $base-font * 2.5——编译时$base-font可能未声明或作用域不对
@each 循环生成语义化标题类,而非仅标签选择器
别只写 h1 { ... } 这种全局规则——它无法复用、无法覆盖、一改全崩。真正可维护的排版系统,得产出 .text-h1、.text-h2 这类工具类,让组件按需携带语义。
循环必须带解构逻辑:
立即学习“前端免费学习笔记(深入)”;
@each $level, $props in $type-scales {
.text-#{$level} {
font-size: map-get($props, "font-size");
line-height: map-get($props, "line-height");
font-weight: map-get($props, "font-weight");
}
}-
&.text-#{$level}写法比直接.text-h1更安全,能嵌套在 BEM 命名空间或媒体查询内 - 每次
map-get()前建议加守卫:@if map-has-key($props, "font-size"),防某个层级漏配字段导致编译中断 - 如果某级标题需要额外样式(如
h2加底部边框),就在循环体内针对$level == "h2"写条件分支,别另起一套规则
响应式排版:在 @media 内套 @each,而不是给每个类加断点
想让 .text-h1 在小屏下变小?别手写 @media (max-width: 768px) { .text-h1 { font-size: 2rem; } } 然后复制粘贴六遍。那等于把 Map 的优势全扔了。
正确路径是把断点也做成 Map,外层 @each 断点,内层 @each 字体层级:
$breakpoints: ("sm": 576px, "md": 768px);
@each $bp-name, $bp-width in $breakpoints {
@media (max-width: $bp-width) {
@each $level, $props in $type-scales {
.text-#{$level} {
font-size: map-get($props, "font-size") * 0.8;
}
}
}
}- 断点 Map 必须是真实 key-value 对,不能是 list;否则
@each迭代顺序不可控,移动端优先失效 - 缩放系数(如
* 0.8)别写死,抽成变量$responsive-scale-sm: 0.8,方便统一调整 - 这种嵌套循环会生成重复 CSS(比如每个断点里都输出
.text-h1),但比手动维护强十倍——改一个系数,所有标题同步响应
如何支持主题化排版:用 data-theme 驱动字体颜色与对比度
SCSS 本身不能运行时换字体色,但可以预编译多套配色逻辑。关键不是改 color 值,而是把颜色和语义绑定进 Map。
例如深色模式下,h1 文字要更亮、行高略松:
$type-themes: (
"light": (
"h1": ("color": #1e293b, "line-height": 1.2),
"h2": ("color": #334155, "line-height": 1.3)
),
"dark": (
"h1": ("color": #f1f5f9, "line-height": 1.25),
"h2": ("color": #cbd5e1, "line-height": 1.35)
)
);再用 @each 配合 [data-theme] 生成规则:
@each $theme-name, $theme-map in $type-themes {
[data-theme="#{$theme-name}"] {
@each $level, $props in $theme-map {
.text-#{$level} {
color: map-get($props, "color");
line-height: map-get($props, "line-height");
}
}
}
}- HTML 必须带
data-theme="dark"属性,JS 切换只需改这个属性值,CSS 自动生效 - 不要试图用
map-get($theme-map, $level)——第二个参数必须是字面量(如"h1"),不能是变量,否则编译失败 - 字体粗细、大小这类不随主题变的属性,仍保留在主
$type-scales里;只把颜色、对比度相关项抽到$type-themes,职责分离
最易被忽略的是:字体层级一旦和主题耦合,map-get() 的键名一致性就变成编译期校验点。一个 "color" 写成 color(无引号),整块主题排版就静默失效——没有报错,只有文字不换色。


















