percentage($i / 12)比(100% / 12) * $i更可靠,因前者为纯数值运算后加单位,避免单位参与导致的链式浮点误差;后者将100%作为带单位值参与四舍五入计算,累积误差使第12列无法精确达100%。

SCSS里直接写100% / 12 * $i会累积浮点误差
这不是编译器 bug,而是 SCSS 数值计算模型决定的:它把 100% 当作带单位的数值参与运算,每次乘除都保留小数位并四舍五入,而 Sass 早期版本(如 3.5)默认只保留 10 位小数,后续版本也未保证无限精度。所以 (100% / 12) * 3 ≠ 25%,而是 24.9999999999%——多列叠加后,第 12 列甚至算不出完整 100%。
- 避免在循环中做链式百分比运算,尤其是涉及除法再乘法的组合
- 不要依赖
100% / N得到“精确等分”,它只是近似值 - 若必须用百分比生成栅格类,优先用整数倍的基准值,比如先算出
$unit: percentage(1/12),再乘以$i
改用percentage()函数能绕过单位参与运算
percentage() 是 SCSS 内置函数,作用是把一个**无单位小数**转为带 % 单位的值,不经过中间浮点运算链。它本质是字符串拼接 + 类型转换,不触发 CSS 单位参与的数值计算流程。
-
percentage(1/12)→8.33333%(由 Sass 运行时精确计算一次) -
percentage($i / 12)→ 直接对整数做除法,再转百分比,结果更可控 - 对比:
(100% / 12) * $i是单位运算,percentage($i / 12)是纯数值运算后加单位
示例写法:
@for $i from 1 through 11 {
.c#{$i} {
width: percentage($i / 12);
}
}为什么percentage(1/12)比手写8.3333333333%更可靠
手写长小数看似“精确”,实则埋了两个坑:一是维护成本高(改列数要全换),二是不同 Sass 版本对字面量小数的解析精度不一致;而 percentage() 把精度控制权交给 Sass 运行时,且语义清晰——你表达的是“十二分之一”,不是“八点三三三三三三三三三三百分比”。
立即学习“前端免费学习笔记(深入)”;
- 当网格从 12 列改为 24 列,只需改
percentage($i / 24),无需重算所有字面量 - 某些构建环境(如旧版 Webpack sass-loader)会对 CSS 字面量做额外截断,但
percentage()输出是编译期确定的字符串,不受影响 - 注意:
percentage()输入必须是数字,percentage("1/12")或percentage(1px / 12)会报错
真正该警惕的不是 SCSS,而是最终 CSS 渲染时的像素舍入
就算 SCSS 输出了完美的 width: 8.3333333333%,浏览器渲染时仍会按父容器宽度四舍五入到最近像素(或 subpixel)。例如父宽 901px,8.3333333333% × 901 = 75.0833...,最终可能取 75px 或 75.08px,取决于引擎和设备像素比。
- 这种误差无法靠 SCSS 消除,只能靠布局机制缓解:Flex/Grid 的分配逻辑比 float + 百分比更容错
- 若必须用百分比 + float,建议配合
box-sizing: border-box和max-width做兜底 - 移动端尤其明显:iOS Safari 对 subpixel 渲染策略保守,同一行多个
33.3333%子项常因累计舍入导致换行


















