应使用两层@each分离断点与列数逻辑:外层遍历$breakpoints生成媒体查询,内层遍历1–12生成对应类名及calc(#{$i}/12*100%)宽;按需启用断点,避免全量冗余输出。

用 @each 遍历断点生成栅格类,但别直接套用媒体查询写法
SCSS 的 @each 本身不生成响应式行为,它只是静态生成 CSS 规则。所谓“响应式栅格”,本质是为不同断点预设一组类(如 .col-6, .col-md-6, .col-lg-4),再配合媒体查询生效。直接在 @each 里嵌套 @media 是可行的,但容易产出冗余、难维护的 CSS —— 尤其当断点和列数交叉组合时。
更合理的做法是:先定义断点映射,再用两层 @each 分离「断点」和「列数」逻辑:
- 外层遍历断点(
$breakpoints),生成对应媒体查询包裹块 - 内层遍历列数(
$columns),生成该断点下的具体类名与flex-basis - 避免把所有断点都塞进每个类里(比如
.col-6不该在md和lg下重复声明)
@each 中访问断点值必须用 map-get,不能直接展开变量
如果你定义了 $breakpoints: (sm: 576px, md: 768px, lg: 992px);,那么在 @each $key, $val in $breakpoints 中,$val 是 576px 这样的值,可以直接用于 min-width;但若想在类名中拼出 col-sm-6,就得用 $key(即 sm)。常见错误是误以为 $val 能当字符串用,结果编译报错 "Invalid CSS after 'col-': expected class name"。
正确示例片段:
@each $breakpoint, $width in $breakpoints {
@media (min-width: $width) {
@for $i from 1 through 12 {
.col-#{$breakpoint}-#{$i} {
flex: 0 0 calc(#{$i} / 12 * 100%);
}
}
}
}
列宽计算用 calc() 而非预计算百分比,否则无法支持 CSS 变量或运行时调整
有人会提前算好 $i / 12 * 100% 并存成变量,比如 $w: percentage($i / 12),但这在 SCSS 中是静态计算,输出后就是固定数字(如 8.33333%)。一旦后续想用 CSS 自定义属性控制栅格基线(比如改成 24 列),就完全失效。
用 calc() 把运算留在 CSS 层,才是可扩展的做法:
-
flex: 0 0 calc(#{$i} / 12 * 100%)→ 输出为flex: 0 0 calc(6 / 12 * 100%),浏览器运行时计算 - 若需适配 24 列系统,只需改分母,无需重写全部类名
- 注意:SCSS 不会简化
calc()表达式,所以不用担心中间步骤污染
不推荐为每个断点都生成完整 1–12 列,按需生成更可控
全量生成会导致 CSS 体积激增(例如 4 个断点 × 12 列 = 48 条规则),而实际项目往往只在 md 及以上才需要响应式列宽,sm 下多用 .col-12 或堆叠布局。
建议做法:
- 基础类(无断点前缀)默认移动端堆叠,仅提供
.col-12和.col-auto - 对
md及以上断点,才启用完整 1–12 列生成 - 用
@if map-has-key($responsive-breakpoints, $breakpoint)控制开关 - 这样既保留灵活性,又避免无意义的 CSS 膨胀
真正麻烦的是断点命名和类名语义的一致性 —— 比如 xl 到底对应 1200px 还是 1400px,这个一旦定下,所有 @each 循环都得跟着对齐,改一处就得全局核对。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











