在动态调整 Grid 布局列数时,许多开发者习惯在 JavaScript 中直接拼接字符串来修改 style.gridTemplateColumns。但本文介绍一种更优雅、更健壮的方案:使用 CSS 变量(Custom Properties)。 核心思路非常简单:不要在 JavaScript 中硬编
如何用JS修改CSS变量动态调整Grid列数
时间:2026-06-01
浏览:318
文章目录
在动态调整 Grid 布局列数时,许多开发者习惯在 JavaScript 中直接拼接字符串来修改 style.gridTemplateColumns。但本文介绍一种更优雅、更健壮的方案:使用 CSS 变量(Custom Properties)。

核心思路非常简单:不要在 JavaScript 中硬编码布局字符串,而是修改一个预先定义好的 CSS 变量,例如 --columnsCount。 这样,布局逻辑保留在 CSS 层,JavaScript 仅负责“发号施令”,实现清晰解耦。
为什么推荐使用 CSS 变量而不是直接修改 style.gridTemplateColumns?
直接拼接字符串的方式(例如 gridContainer.style.gridTemplateColumns = `repeat(${n}, 1fr)`)看似简单,实则存在不少隐患。比如容易漏写单位、引号嵌套混乱,更关键的是,它将布局样式与业务逻辑紧密耦合在一起。后续若需实现响应式覆盖或添加过渡动画,会变得相当麻烦。
而 CSS 变量天生支持级联与继承,带来以下好处:
- 可通过
@media查询轻松覆盖。例如,小屏设备上强制--columnsCount: 1,大屏上恢复为4。 - 支持 CSS 过渡效果。只要为
grid-template-columns属性添加transition,当变量值变化引起列宽改变时,即可呈现平滑缩放动画(注意:该效果仅适用于轨道尺寸变化,新增或删除轨道项不会触发过渡)。 - 减少 JavaScript 频繁操作 DOM 样式属性的次数,有助于避免强制同步布局(Layout Thrashing)带来的性能问题。
setProperty 的调用时机与选择器范围需精确
使用该方法的关键在于:确保 JavaScript 修改的变量作用域能被目标网格元素正确捕获。常见错误是将变量定义在全局的 :root 上,而网格容器使用某个局部类选择器,导致修改不生效。
正确做法如下:
- 若网格容器的类名为
.gridBox,则变量应定义在该选择器内:.gridBox { --columnsCount: 3; grid-template-columns: repeat(var(--columnsCount), 1fr); } - 在 JavaScript 中,选中具体容器元素进行修改:
const gridBox = document.querySelector('.gridBox'); gridBox.style.setProperty('--columnsCount', '4'); - 除非确实需要变量全局生效,否则避免使用
document.documentElement.style.setProperty。
动态列数搭配 minmax() 更健壮
单纯使用 repeat(var(--columnsCount), 1fr) 可能在容器宽度较小时引发问题。例如列数固定为 4,容器仅 300px 宽,每列只有 75px,内容会被严重挤压。
以下经验可供参考:
- 可考虑使用
repeat(auto-fit, minmax(250px, 1fr))。在此模式下,浏览器会自动计算合适列数,可能无需 JavaScript 动态控制列数。 - 若业务要求精确控制列数(如数据报表需固定 3 列),则必须坚持变量方案。此时建议配合
max-width和overflow-x: hidden等样式防止内容溢出。 - 需注意兼容性:IE11 不支持在
grid-template-columns中使用var()。可借助@supports (display: grid)进行特性检测,并准备 Flexbox 等回退方案。
resize 监听并非万全之策,ResizeObserver 更精准
为实现响应式,许多开发者会监听 window.resize 事件来动态调整列数。但此方法存在两个典型问题:一是窗口拖拽时事件触发过于频繁,容易导致性能问题;二是若仅网格容器自身尺寸变化(如侧边栏展开收起),窗口事件不会被触发。
更现代的解决方案是使用 ResizeObserver API:
- 直接观察网格容器自身的尺寸变化:
new ResizeObserver(() => { updateColumnsByWidth(gridBox); }).observe(gridBox); - 在
updateColumnsByWidth函数内,根据gridBox.clientWidth计算出当前应显示的列数,再调用setProperty更新变量。 - 此方法比监听全局
resize事件更精准,且不依赖窗口对象,特别适合嵌入式组件或微前端等独立场景。
技术难点往往不在于如何改变变量值,而在于列数变化时,如何保证页面内容不跳动、不闪烁、不撑破父容器。这考验开发者是否提前做好功课:例如使用相对单位设置 gap,为子项统一添加 box-sizing: border-box,并妥善处理子项的 max-width 和文本换行策略。将这些细节落实到位,动态布局才能真正实现丝滑流畅。
实用工具推荐
绿化、压缩、噪点和虚拟水印,自由调节做旧程度。
选择画质和输出格式,预览压缩前后的大小。