了解 CSS Grid Lanes
Learn CSS Grid Lanes
2026年6月10日
一句话判断
原生 CSS 终于干掉了瀑布流 JS 库,还顺手用 flow-tolerance (流容差) 解决了键盘焦点乱跳的无障碍大坑。
这场 Session 讲了什么
前端搞瀑布流(Masonry Layout)被折磨了十几年。用 Flexbox 会留大白,用 CSS Grid 会把图片拉伸或裁剪,最后大家只能捏着鼻子引个几十 KB 的 JS 库去算 DOM 高度。现在 Safari 26.4 直接给了个 display: grid-lanes,三行代码搞定。它介于 Flexbox(一维)和 Grid(二维)之间,只锁死一个轴(比如列宽),另一个轴(行高)完全交给内容自己撑开。
这对写 WebView 的 iOS 开发者或者纯前端来说是大利好。以前在 WKWebView 里搞瀑布流,JS 算高度还会触发多次 reflow(重排),现在直接交给 WebKit 渲染引擎在 C++ 层算,性能和滚动流畅度直接起飞。
值得深挖的点
flow-tolerance 拯救了瀑布流的无障碍体验
这场 Session 放在 Accessibility & Inclusion (无障碍与包容性) Track 绝不是偶然。传统瀑布流算法是“哪列最短就放哪列”,这会导致一个致命问题:DOM 顺序和视觉顺序脱节。比如第一行左边图片极高,右边图片极矮,第二行的元素视觉在右边,但 DOM 里排在左边。键盘用户按 Tab 键时,焦点会在屏幕上疯狂左右横跳,屏幕阅读器读出来的顺序也是乱的。
Apple 引入了 flow-tolerance 属性,默认值是 1em。它的逻辑是:如果最短列和次短列的高度差在 1em 以内,浏览器会优先把元素放进 DOM 顺序更靠前的列(也就是左边的列),而不是死磕绝对的最短列。这个极其微小的视觉妥协,换来了完美的线性阅读和焦点顺序。这才是大厂做基础组件的格局,不只是为了“好看”,更是为了“可用”。
单轴约束的 Trade-off
Grid Lanes 有个硬性规定:你只能选 grid-template-columns (网格模板列) 或者 grid-template-rows (网格模板行),不能同时定义两个。这看起来像是功能阉割,其实是极其聪明的设计。
如果允许双轴控制,那就退化成了普通的 CSS Grid,又会面临单元格留白的问题。Grid Lanes 的价值就是“内容决定另一轴的尺寸”。放弃对行高的控制权,换来了元素紧密排列(Pack tightly)且绝不扭曲(No distortion)的保证。对于图片流、卡片流这种高度不可预测的场景,这种“半自动”模式比完全手动控制省心太多。你只管控制列宽,剩下的 WebKit 帮你算。
代码片段
1. 三行代码实现基础瀑布流
场景:最基础的等宽三列瀑布流,告别 JS 计算。
.gallery {
display: grid-lanes; /* 启用 Grid Lanes 布局模式 */
grid-template-columns: repeat(3, 1fr); /* 定义3个等宽列,fr 表示比例 */
gap: 10px; /* 设置元素间距 */
}
坑:千万别顺手写上 grid-template-rows,Grid Lanes 只能控制一个轴,写了行模板会直接报错或失效。
2. 响应式自适应列宽
场景:不用写媒体查询,让浏览器根据屏幕宽度自动决定塞下几列。
.responsive-feed {
display: grid-lanes;
/* 每列最小 200px,最大平分剩余空间,自动填充 */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 16px;
}
坑:auto-fill 在容器极窄时可能会导致单列占满,如果需要强制至少两列,得改用具体的数字或调整 minmax 的最小值。
3. 跨列与子网格对齐
场景:某个重点卡片需要占两列,且内部元素要和外部网格对齐。
.featured-card {
grid-column: span 2; /* 让这个卡片横跨 2 列 */
display: grid-lanes; /* 内部也开启 Grid Lanes */
grid-template-columns: subgrid; /* 继承父级的列轨道定义 */
}
坑:subgrid (子网格) 要求父级必须有明确的网格轨道定义,如果父级是用 Flexbox 布局的,subgrid 会直接失效。
最佳实践
老项目里如果用了 Masonry.js 或 Isotope 这种第三方库,建议直接做渐进增强(Progressive Enhancement)。用 @supports (display: grid-lanes) 包一层,支持的浏览器走原生 CSS,不支持的继续降级用 JS 库。这样既能享受 WebKit 原生渲染的 60fps 滚动,又不会搞挂老设备。
新项目无脑上 grid-lanes。但要注意,因为行高是内容撑开的,如果你的卡片里有异步加载的图片,一定要在 CSS 里给图片设置 aspect-ratio (宽高比),否则图片加载完成后高度突变,会导致下方所有元素重新计算位置,产生严重的布局偏移(CLS)。
还有什么值得关注
- 砖墙模式 (Brick Wall):把
grid-template-columns换成grid-template-rows,瀑布流直接横向流转,变成类似时间轴的砖墙布局。 - Web Inspector 原生支持:Safari 开发者工具加了 Grid Lanes 专属 Overlay,能直接看到每个元素的 DOM 顺序编号,调
flow-tolerance时一目了然。 - WKWebView 同步受益:虽然 Session 强调 Safari 26.4,但底层是 WebKit 的改动,意味着 iOS/macOS 上的 WKWebView 也会同步获得这个能力,对原生 App 内嵌 H5 体验提升巨大。