真正稳的方案是 auto-fit + 轨道高度反推 + 父容器控制:用 auto-fit 替代 auto-fill 避免空列占位,按最小列宽反推 grid-auto-rows 高度(如 320px 宽对应 180px 高),父容器设 display: block 或 grid 并配 aspect-ratio: 16/9 和 overflow: hidden,video 设 width: 100%; height: 100%; object-fit: cover; 禁用 aspect-ratio 和 max-height。

别用 auto-fill 配 aspect-ratio,高度会跳、比例是假的——真正稳的方案是 auto-fit + 轨道高度反推 + 父容器控制。
为什么 auto-fill + aspect-ratio 会让视频高度忽高忽低
常见写法:grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)),再给 video 加 aspect-ratio: 16/9。问题在于:
-
1fr按剩余空间均分宽度,但aspect-ratio只约束宽高比,不锁死绝对高度;同一行里列宽不同 → 视频实际宽度不同 → 高度反复重算 → 上下跳动 -
auto-fill强制预留所有可能列轨道,空列也占位,干扰 Grid 行高计算逻辑 - 浏览器对
aspect-ratio的实现仍依赖子元素渲染流,在 Grid 中优先级低于轨道尺寸,video自身设aspect-ratio基本无效 - 加
max-height会和aspect-ratio冲突,Safari 和 Chrome 至今未修复该 bug,必出上下黑边
用 auto-fit + grid-auto-rows 锁死物理高度
核心思路:把高度控制权从 video 手里收回来,交给 Grid 轨道本身。
- 按最小列宽反推目标高度:比如最小列宽设为
320px→ 对应高度为320 * 9 / 16 = 180px→ 设grid-auto-rows: minmax(0, 180px) - 容器写成:
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr))(注意是auto-fit,空列自动合并) -
video样式统一:width: 100%; height: 100%; object-fit: cover;,禁用aspect-ratio和max-height - 若需响应更精细(如小屏缩到
240px宽),可用 CSS 变量:grid-auto-rows: calc(var(--col-width) * 9 / 16),再用媒体查询更新--col-width
父容器必须是块级且显式声明 display
aspect-ratio 只作用于块级容器,不是 video 元素自身——这点极易被忽略。
立即学习“前端免费学习笔记(深入)”;
- 视频父容器(比如
.gallery-item)必须设display: block或display: grid;如果没设display,默认是 inline,aspect-ratio直接失效 - 推荐在父容器上设
aspect-ratio: 16/9+overflow: hidden,再让video填满它:width: 100%; height: 100%; object-fit: cover; - 某些安卓 WebView 对
aspect-ratio支持不稳定,记得给父容器加min-height: 0,防止 Grid 轨道高度计算异常 - iOS Safari 默认拦截未激活视频的 pointer 事件,尤其当卡片加了
opacity: 0.99或transform时更明显;必须同时加playsinline和webkit-playsinline属性
auto-fill 在什么场景还能用
仅当你需要模拟「固定网格坐标系」时才考虑 auto-fill,比如视频时间轴预览、带编号的帧采样面板——这些场景要求空白格子占位来维持行列索引一致性。
- 必须显式设
grid-auto-flow: row dense,否则空轨道会导致后续项错位 - 需搭配
grid-column: span X手动控制跨列,否则空轨道会让内容偏移 - 移动端慎用:iOS Safari 15.4 以下版本对
auto-fill+minmax()的轨道计数有偏差,容易漏列
真正麻烦的从来不是怎么写那几行 CSS,而是有没有意识到:Grid 的轨道高度才是视频画廊稳定的锚点,而不是子元素的 aspect-ratio;以及,父容器的 display 类型和是否预留了足够空间,往往比写错一个参数影响更大。


















