必须手写 interpolate() 函数实现流式排版,因 clamp() 是运行时字符串表达式,无法参与 Sass 编译期运算或传入需数值的混入;interpolate() 返回带单位的 Sass 数值,可剥离单位后用于判断、计算及第三方工具。

不能靠 clamp() 生成流式排版 CSS,它不参与 Sass 编译期运算,也没法喂给 sgl-heading 这类需要数值的混入;真正可用的是手写 interpolate() 函数,做单位一致、边界可控的线性内插。
为什么 interpolate() 必须自己写,不能用 clamp() 替代
clamp() 是浏览器运行时执行的字符串表达式,Sass 拿不到计算结果——你没法把它塞进 @if $font-size > 16px 做判断,也不能传给 sgl-margins($ratio),因为后者要的是纯数字(比如 1.42),而 clamp(14px, 0.875rem + 0.012vw, 18px) 返回的是字符串。流式排版的核心是“在编译期就确定每个断点下的确切数值”,然后让这些数值参与后续逻辑。
-
interpolate()输出的是带单位的 Sass 数值(如15.32px),可直接参与math.div()、@if判断、或转成无单位数喂给排版工具 -
clamp()只能用于最终输出层,比如给根字体设一个兜底:html { font-size: clamp(14px, 0.875rem + 0.012vw, 18px); } - 想实现「320px→14px,768px→16px,1200px→18px」这种三段式,得套两次
interpolate(),clamp()根本不支持
interpolate() 函数怎么写才不出错
网上抄来的两参数版本在真实项目里基本不可用。必须处理单位对齐、越界截断、以及和 Sassy-Gridlover 等工具的兼容性。下面这个是经过多个设计系统验证的最小可行版本:
@function interpolate($start-val, $end-val, $start-viewport, $end-viewport, $current-viewport) {
$ratio: clamp(0, ($current-viewport - $start-viewport) / ($end-viewport - $start-viewport), 1);
@return ($start-val + ($end-val - $start-val) * $ratio);
}
- 所有输入值单位必须一致:
320px、768px、100vw混用会报Incompatible units px and vw;统一用px,再把100vw换算成基准屏宽(比如375px) -
clamp(0, ..., 1)不可省:防止$current-viewport小于$start-viewport或大于$end-viewport时返回负数或超 1 的比率 - 若要输出
rem,先换算好基准:interpolate(0.875rem, 1.125rem, 320px, 768px, $screen-width),别拿14px和1.125rem直接算
和 Sassy-Gridlover 配合时最常踩的坑
sgl-heading()、sgl-margins() 这些混入只认无单位数值(例如 $scale: 1.42),但 interpolate() 默认返回 1.42rem——单位不剥离,直接编译失败或行高错乱。
- 必须手动剥离单位:
$val: $val / 1rem,或用@if unitless($val) == false { $val: $val / 1rem; } - 别写成
sgl-heading($scale: interpolate(...)),先赋值:$h2-scale: interpolate(1.2, 1.5, 320px, 768px, $screen-width) / 1rem;,再传$h2-scale - 如果用了
sgl-font-size(),它内部会再乘一次1rem,所以你传进去的必须是纯数字,否则变成1.42rem * 1rem,单位爆炸
用 math.div() 和 math.pow() 做配套计算
流式排版不只是字号,还包括行高、字间距、margin、padding——它们往往按同一套比例缩放。这时别硬写 1.42 * 1.2,用 math 模块更稳:
- 行高缩放:
$line-height: math.div(interpolate(1.4, 1.6, 320px, 768px, $screen-width), 1rem); - 字间距阶梯:
$letter-spacing: math.pow(0.95, $level);($level越高,收紧越明显) - 避免重复计算:
$base-ratio: interpolate(1.2, 1.5, 320px, 768px, $screen-width) / 1rem;,后面全用它 - 旧版 LibSass 不支持
math,确认构建环境是 Dart Sass;CI 报Invalid CSS after "math.div"就是这个原因
流式排版最难的不是写函数,而是保证所有环节单位归一、数值可传递——从 interpolate() 输出,到剥离单位,再到喂给第三方混入,每一步都可能因单位残留或类型错配崩掉。别省那两行 / 1rem。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











