真正有效的解法是加虚拟滚动,如react-window或IntersectionObserver,只挂载可视区域±2行项;避免全量DOM渲染、动态改grid-template-columns、visibility:hidden等引发重排的写法。
Grid 本身不卡,卡的是全量 DOM 渲染。用 display: grid + repeat() 渲染上千项?本质仍是同步创建并挂载所有 grid-item,浏览器要 layout、paint、composite 全流程走一遍——和用 flex 或 div 堆没区别。
真正有效的解法不是调 Grid 参数,而是加虚拟滚动(virtual scroller)。比如 react-window 或原生 IntersectionObserver + scrollHeight 计算可视区域,只挂载当前屏内 ±2 行的项。
content-visibility: auto 在 Grid 直接子项上起效——Flex/Grid 容器里它常失效或错位contain-intrinsic-size 必须写在每个 grid-item 上,且不能是 0 或空值;横向长表可设 contain-intrinsic-size: 800px 0(高度由内容撑开)items: N 预估总数,否则会反复重排每次改 style.gridTemplateColumns 字符串,浏览器都得重新解析、测量所有子项、分配 fr 空间——尤其父容器有 flex 嵌套或监听 resize 时,卡顿指数级上升。
正确做法是抽离比例为 CSS 变量,JS 只改变量值:
/* CSS */.grid-container {grid-template-columns: calc(var(--col1) * 1fr) calc(var(--col2) * 1fr) 1fr;}
el.style.setProperty('--col1', '2'),不碰 gridTemplateColumns
requestAnimationFrame 节流,合并到单帧scroll 或 mousemove 回调里直接拼字符串赋值visibility: hidden 的坑在于:元素仍参与 Grid 轨道计算,浏览器照旧预留空间、算行高列宽、触发 grid-auto-rows —— 数据量大时开销惊人。
display: contents 让元素“消失”且彻底退出布局流,父容器不再为其生成盒模型grid-column/grid-row 数值定位更可控,比依赖 grid-area 字符串命名更轻量margin 或 min-height 显式撑开,而非靠隐式轨道嵌套 ≥3 层 + 中间层用 min-content 或 auto?Chrome DevTools 的 Rendering tab 里会看到重复 “Layout” 事件——这是浏览器被迫多轮测量导致的隐式重排链。
width/height,切断子网格反向影响父尺寸的路径contain: layout paint(Chrome 85+ / Firefox 90+)隔离中间层渲染边界subgrid 或 display: contents 拉平结构,避免套娃grid-template-areas 在 >100 项时解析开销明显,动态生成优先用数值定位 grid-column: 2 / 4
性能瓶颈从来不在 Grid 语法本身,而在你让浏览器反复猜尺寸、反复重排、反复升合成层。盯紧 DevTools 的 Layout 和 Paint 阶段耗时,比调参数更重要。