应避免在less中直接使用calc(100% / @n),因其编译期预计算会产生高精度小数导致总和不足100%,引发布局换行;正确做法是用percentage()生成字符串宽度并配合递归mixin安全输出栅格类。

直接用 percentage() 配合递归 mixin 生成栅格类,比硬写 calc(100% / @n) 更可靠——后者在 Less 编译期会尝试预计算,产生带多位小数的字面量(如 calc(33.333333%)),浏览器渲染时截断导致 12 列加起来不足 100%,卡片意外换行。
为什么 calc(100% / @n) 在 Less 中不能用
Less 不是运行时引擎,它在编译阶段就要把表达式算出结果。当 @n 是变量(比如 @grid-columns: 12)时,旧版 Less 直接报错 “Operation on an invalid type”;新版即使能算,也会输出高精度小数,CSS 解析器不保证保留全部位数。更关键的是:百分比总和一旦低于 100%,Flex 或 float 容器就会触发换行,布局崩掉。
正确做法是让宽度值在编译期就固化为字符串:
-
@col-width: percentage(1 / @grid-columns);→ 得到"8.333333%" - 再拼接:
width: ~"(@{col-width} * @{span})";→ 输出width: 25%; - gutter 留给浏览器 runtime 处理:
margin-left: calc(var(--gutter, 1rem) / 2);
用递归 mixin 安全生成 .col-1 到 .col-12
Less 没有 @for,所谓“循环”本质是带守卫的递归调用。漏掉终止条件或参数传错,要么无限递归报错,要么只生成一个类。
标准写法必须包含三要素:
- 守卫条件用
when (@n > 0),不用=或,避免整数精度偏差导致死循环 - 每次递归显式传参:
.make-col((@n - 1), @grid-columns),不依赖外部变量 - 类名拼接用
.col-@{n}(花括号不可省),否则.col-@n会被解析成变量引用
入口调用写成 .make-col(@grid-columns, @grid-columns),确保从最大列数开始生成。
断点与列数解耦,避免全局强耦合
把 @grid-columns: 12 写死在全局,改一个断点就得搜三遍文件。响应式栅格的核心是「每个断点拥有独立列数」:
- 定义断点变量:
@bp-sm: 576px; @bp-md: 768px; @bp-lg: 992px; - 按断点拆开列数:
@grid-columns-sm: 4; @grid-columns-md: 8; @grid-columns-lg: 12; - 用
.each()(Less 4.0+)遍历断点 map,内部再调一次列循环;别嵌套两层.each(),旧版 Less 容易崩溃 - 媒体查询内重算宽度:
@media (min-width: @bp-md) { .make-col(@grid-columns-md, @grid-columns-md); }
.offset-* 类没效果?先检查父容器布局上下文
偏移类本质是 margin-left,它不改变元素定位方式。如果父容器没启用 Flex、Grid 或 float,margin-left 只会把元素往右推,但可能引发换行或脱离预期流。
Offset 必须配合布局上下文才生效:
- Flex 容器:确保父级有
display: flex,且子项未设flex-wrap: wrap(否则 margin 可能被忽略) - Grid 容器:优先用
grid-column-start,.offset-*仅作降级 fallback - 浮动布局:父级需清除浮动,且子项本身要
float: left
最容易被忽略的一点:所有栅格类(包括 offset)都默认基于固定 gutter 值(如 --gutter: 1rem)。如果项目里用的是 rem/vw 混合单位,或者通过 JS 动态注入根字体大小,这些 CSS 变量必须在 :root 中提前声明,否则 offset 计算会失效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











