媒体查询仅负责断点切换,不实现阶梯渐变;字号阶梯需由SCSS函数或CSS clamp() + 自定义属性驱动,避免冗余CSS与维护困难。

直接说结论:媒体查询本身不负责“阶梯渐变”,它只做断点切换;真正的字号阶梯必须由 SCSS 函数或 CSS clamp() + 自定义属性驱动,媒体查询只是在不同视口下切换这些预设值。硬套 @media 在每个 h1–h6 里写 font-size,会生成冗余 CSS,且无法统一缩放。
为什么不能在 @for 循环里嵌 media 查询
常见错误是这样写:
@for $i from 1 through 6 {
@media (max-width: 768px) {
h#{$i} { font-size: calculate-scale($i, 1.125rem); }
}
}这会导致编译出 6 个独立的 @media 块,浏览器无法合并,CSS 体积膨胀,且后续想统一调暗色模式字号时得改 6 处。更关键的是——calculate-scale() 在旧版 Dart Sass(如 1.15)里调用 pow() 会报 Undefined function "pow" 错误。
- 正确做法是把断点字号提前存为数组,比如
$heading-sizes-sm: 1.5rem, 1.25rem, 1.125rem, 1rem, 0.875rem, 0.8125rem; - 再用
@each或@for一次性生成所有h1–h6,避免重复 media 块 - 函数内部避开
pow():用查表法nth($scales, $level)或线性公式$base * (1.2 - $level * 0.15)
用 clamp() + CSS 自定义属性实现无编译依赖的响应式阶梯
如果你不想依赖 SCSS 编译,纯 CSS 方案可用 clamp() 搭配 :root 变量。但注意:clamp() 是单值自适应,不是阶梯——所以得为每级标题单独设变量:
立即学习“前端免费学习笔记(深入)”;
:root {
--h1-size: clamp(1.5rem, 4vw, 2.5rem);
--h2-size: clamp(1.25rem, 3.5vw, 2rem);
--h3-size: clamp(1.125rem, 3vw, 1.75rem);
}
<p>h1 { font-size: var(--h1-size); }
h2 { font-size: var(--h2-size); }
h3 { font-size: var(--h3-size); }这个方案绕过所有构建工具,但缺点也很明显:
- 无法像 SCSS 那样用一个
$ratio统一调控全部层级缩放比例 - 设计师改 h4 缩放比时,得手动算新
clamp()三元组,易错 - 小屏下
clamp(min, fluid, max)的min若设太小(如0.75rem),可能糊字
SCSS calculate-scale() 函数的参数陷阱
函数签名 @function calculate-scale($level, $base: 1.25rem, $ratio: 0.85) 看似简单,但三个参数都有坑:
-
$level必须是整数 1–6,传h2就得传2,别传字符串或变量名 -
$base别写死16px,应对接$type-base: 1rem这类主题变量,否则换根字体大小时全失效 -
$ratio: 0.85是实测平衡点:0.8 太激进,h6掉到0.6rem小屏难读;0.9 又太平,h1–h6 视觉节奏塌陷
最易忽略的一点:这个函数只管“计算”,不管“应用”。你仍需配合媒体查询切换 $base 或整个 $scales 数组——函数本身不感知断点。


















