repeat() 的列数参数不支持 CSS 变量,因规范禁止且变量仅字符串替换;安全用法包括 gap、minmax() 内部和 calc()(部分场景);精确控制列数需 JS 动态设置 gridTemplateColumns,或改用 auto-fit + minmax() 自适应方案。

直接用 var(--cols) 控制 repeat() 列数在所有浏览器中都会失效——这不是兼容性问题,而是 CSS 规范明确禁止的语法限制。
为什么 repeat(var(--cols), 1fr) 总是不生效
CSS 变量只做字符串替换,不参与表达式求值。repeat() 的第一个参数必须是字面量数字(如 3),不能是变量。即使 --cols: 3 定义正确,repeat(var(--cols), 1fr) 也会被浏览器静默丢弃,Computed 面板里 grid-template-columns 显示为空或 initial。
-
--cols: "3"(带引号)、--cols: 3px(带单位)、--cols: 3.0(小数)全都会失败 - @property 也无法绕过该限制,目前所有浏览器均未支持
- 检查开发者工具的 Computed 面板,若
grid-template-columns没值,基本可锁定是这个原因
真正能用 CSS 变量的地方有哪些
变量在以下位置是安全且广泛支持的(Safari 14.1+、Chrome、Firefox、Edge):
-
gap:但必须带单位,--gap: 16px✅,--gap: 16❌;建议拆成row-gap: var(--row-gap)和column-gap: var(--col-gap)更稳妥 -
minmax()内部:minmax(var(--min-width), 1fr),其中--min-width: 250px有效 -
calc()表达式:width: calc(var(--gap) * 2),但嵌套如calc(var(--cols) * 2)在多数浏览器中仍无效 - IE11 完全不支持以上任何用法,需用
@supports (display: grid)包裹降级
要精确控制“就是 N 列”,必须用 JS 动态设置 gridTemplateColumns
这是目前唯一跨浏览器、语义清晰、可控性强的方案。关键不是“改变量”,而是把变量值读出来,拼成合法的轨道定义,再写入内联样式:
立即学习“前端免费学习笔记(深入)”;
- 先确保变量作用域对齐:在目标网格容器上定义
--cols,比如.grid { --cols: 3; },而不是只挂:root - JS 中读取并转换:
const n = parseInt(getComputedStyle(gridEl).getPropertyValue('--cols').trim()) - 写入样式:
gridEl.style.gridTemplateColumns = `repeat(${n}, minmax(0, 1fr))`(注意加minmax(0, 1fr)防窄屏压缩) - 避免高频调用:每次设置都触发重排,Grid 计算成本高于 Flex,resize 或滚动中慎用
更轻量、更推荐的替代方案:auto-fit + minmax()
如果你实际要的是“根据容器宽度自动适配列数”,而不是“必须等于某个变量值”,那完全不用 JS:
-
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)))—— 浏览器自动计算最多能塞几列,窄屏退为 1 列,宽屏自然铺满 - 配合媒体查询兜底:
@media (max-width: 480px) { .grid { grid-template-columns: 1fr; } } - 别在媒体查询里硬写
repeat(2, 1fr),会和auto-fit冲突,导致列数卡死、高度错位 - 间隙统一用
gap,子项千万别加margin,否则会破坏自动换行逻辑
最容易被忽略的是:CSS 变量本身不会触发重排,但它的值一旦用于 grid-template-columns,就必须通过合法语法接入——而 repeat() 的列数参数恰恰是唯一不允许变量的位置。要么换思路用 auto-fit,要么老实用 JS 拼字符串,没有中间路线。


















