直接用%写网格列宽会出错,因Sass中%是取模运算符而非百分比单位,且CSS百分比依赖容器宽度;应使用percentage()函数传入小数转换,如percentage(0.2)→20%。

为什么直接用 % 写网格列宽会出错
很多人写 grid-template-columns: 20% 30% 50% 看似合理,但实际在 grid 中,百分比列宽是相对于网格容器宽度计算的——而如果容器本身没有明确宽度(比如 width: 100% 或固定值),或者父级是 flex 容器、绝对定位等场景,% 就会失效或表现异常。更关键的是:Sass 的 % 运算符是取模(modulo),不是百分比单位,20% 30% 会被解析成 “20 除以 30 的余数”,直接报错。
用 Sass 的 percentage() 函数生成合法 CSS 百分比值
percentage() 是 Sass 内置函数,作用是把小数转为带 % 单位的 CSS 值,比如 percentage(0.2) → 20%。它不参与运行时计算,只在编译期转换,所以安全、可预测。
常见误用:percentage(20) 错——它会变成 2000%;正确写法必须传小数:
@function grid-col($fraction) {
@return percentage($fraction);
}
.grid-3-4-5 {
grid-template-columns: grid-col(3/12) grid-col(4/12) grid-col(5/12);
}
// 编译后 → grid-template-columns: 25% 33.33333% 41.66667%;
- 分母用总列数(如 12)保证加起来是 100%,避免四舍五入误差累积
- 避免用
1/3这类浮点精度不稳定的分数,改用4/12更可控 - 不要在
percentage()外再加%,否则变成25%%,CSS 解析失败
动态生成多组网格列配置的实用封装
手写每组比例太累,用 Sass 列表 + @each + percentage() 批量生成:
立即学习“前端免费学习笔记(深入)”;
$grid-presets: (
"fluid-2": (1, 1),
"sidebar-main": (1, 3),
"header-nav-main": (2, 1, 9)
);
@each $name, $ratios in $grid-presets {
.grid-#{$name} {
$total: math.sum($ratios...);
$cols: ();
@each $r in $ratios {
$cols: append($cols, percentage($r / $total), comma);
}
grid-template-columns: #{$cols};
}
}
注意点:
- Sass 4.0+ 需启用
math模块(@use "sass:math"),旧版用unitless()+ 手动除法 -
append(..., comma)保证生成带逗号分隔的列表,否则 CSS 会连成一串 - 如果项目仍用 Dart Sass 1.32 以下版本,
math.sum()不可用,得用循环累加
响应式网格中 percentage() 的局限与绕过方式
纯百分比列在小屏下容易过窄、文字换行失控。此时 percentage() 本身没问题,但策略要变:
- 别只靠百分比:混用
minmax(200px, 1fr)或clamp(),让列有弹性底线 - 媒体查询里重定义
grid-template-columns,而不是试图用percentage()算不同断点的值 - 如果真要动态算断点比例(比如从 3 列变 2 列),用
@if分支 + 不同$ratios列表,别在percentage()里塞条件逻辑
最常被忽略的一点:CSS Grid 的 fr 单位本质就是“剩余空间按比例分配”,多数场景下比手动算百分比更鲁棒——percentage() 只应在必须输出具体百分比值(如对接旧 JS 插件、需要精确像素对齐)时才用。


















