video元素直接设aspect-ratio无效,因其是替换元素,宽高比由视频元数据决定;必须用外层容器设aspect-ratio: 16 / 9并配合width: 100%、video填满及移除内联宽高属性,否则将导致高度塌陷和cls。

直接在 video 标签上写 aspect-ratio: 16 / 9 无效——这不是你代码写错了,是浏览器规范行为;必须用容器包裹并设 aspect-ratio,再让 video 填满它,否则加载时高度塌陷、CLS(布局偏移)不可避免。
为什么 video { aspect-ratio: 16 / 9 } 会失效
video 是替换元素(replaced element),其宽高比由视频文件元数据决定,CSS 的 aspect-ratio 对它不生效。浏览器会直接忽略该声明,在开发者工具里看到的 computed styles 中状态为 “inactive”。常见现象包括:
- 页面刚加载时
video高度为 0,只显示一条细线 - 宽度正常但高度没撑开,内容被裁切或留大片黑边
- Safari 15.4–16.3 在
display: flex父容器中完全不计算高度
正确写法:三层结构缺一不可
核心就三步,漏任何一项都会导致比例失控或 CLS:
- 用
<div class="video-wrapper"> 包裹 <code><video></video>,移除video标签上的width和height属性(如width="640" height="360"),否则会覆盖 CSS 控制 -
.video-wrapper必须设width: 100%(或明确的max-width),再加aspect-ratio: 16 / 9;单独写aspect-ratio会导致容器塌陷 -
video元素设width: 100%; height: 100%; object-fit: cover(或contain),并加overflow: hidden到 wrapper 防止溢出 - 动态比例(如后端返回
{ w: 3840, h: 2160 }):必须约分为最简整数比(gcd(3840, 2160) === 240→"16 / 9"),别用小数1.777,精度误差易引发 1px 黑边 - 父容器是
display: flex:Safari 15.4–16.3 会忽略aspect-ratio,临时解法是加align-items: start或改用display: grid - 兼容旧浏览器:必须用
@supports not (aspect-ratio: 1 / 1)包裹降级方案(padding-top: 56.25%+position: relative),平级写会导致旧浏览器回退到无约束状态,CLS 更严重
不同场景下的关键细节
实际项目中不能硬套死 16 / 9,得按需调整:
容易被忽略的渲染边界
很多人以为设了 aspect-ratio 就万事大吉,其实它只管容器盒子尺寸,不管内部怎么显示。如果忘了配 object-fit 或漏了 overflow: hidden,视频可能拉伸变形、边缘溢出,反而放大视觉跳动。更隐蔽的是:在 SSR 或懒加载场景下,若 wrapper 没触发 BFC(比如没设 display: block 或 position: relative),首次渲染仍可能高度为 0——这个点调试时很难定位,得靠 computed styles 里 aspect-ratio 是否显示为 “active” 来确认。











