用<video>标签+position:fixed+object-fit:cover是iOS/Chrome兼容最佳方案;100vh因地址栏收放、缩放等动态变化导致黑边,应改用fixed定位四角;需设z-index:-1、禁用min-width/min-height、优先1080p+源、加transform:translateZ(0)促GPU合成、必带muted/autoplay/playsinline/webkit-playsinline属性、双格式source+poster兜底。

直接用 <video> 标签 + position: fixed + object-fit: cover,其他写法基本都会在 iOS 或 Chrome 上出问题。
为什么 width: 100vw; height: 100vh 会留黑边或错位
这个组合看似“铺满”,实则依赖初始视口尺寸。iOS 地址栏收放、页面缩放、滚动条出现时,100vh 会跳变,视频立刻露白或裁切异常;桌面端窗口缩放也会复现。它不是“固定在视口”,而是“按初始尺寸撑开”。
- 正确做法是用
position: fixed; top: 0; left: 0; width: 100%; height: 100%—— 真正钉死四角,不受文档流和视口动态变化干扰 - 必须设
z-index: -1,否则会盖住所有内容(包括按钮、表单) - 禁用
min-width: 100%或min-height: 100%,它们会破坏object-fit的计算逻辑
object-fit: cover 是唯一靠谱的填充方式
fill 强制拉伸,人像变形、文字压扁;contain 必然留黑边;scale-down 行为不可控。只有 cover 能在保持原始宽高比前提下,裁切溢出部分,实现视觉上“真正覆盖”。
- 视频源分辨率不能太低(如 720p 在 4K 屏上
cover后会模糊),优先换 1080p+ 源,别妥协用fill - 移动端需额外加
transform: translateZ(0)或will-change: transform,促 GPU 合成,防卡顿闪动 - 不要给
<video>设background-image—— 浏览器根本不支持视频地址作为 CSS 背景值
autoplay 失效?缺这四个属性一个都不行
Chrome、Safari、Firefox 全部拦截非静音自动播放,且 JS 调用 .play() 无效(抛 DOMException)。必须在 HTML 标签里一次性写全:
立即学习“前端免费学习笔记(深入)”;
-
muted:必须显式声明,JS 后续设置太晚 -
autoplay:触发播放逻辑的开关 -
playsinline:iOS Safari 生死线,不加就跳原生全屏播放器 -
webkit-playsinline:旧版 iOS Safari 兼容补丁,加了不亏
推荐最小集合:<video muted autoplay playsinline webkit-playsinline loop preload="auto">。只写 autoplay 等于没写。
移动端适配与降级绕不开的坑
iOS 安全区域、刘海屏、地址栏跳变让 100vh 不可靠,但 100dvh(动态视口高度)目前仅 Chrome 104+ 和 Safari 16.4+ 支持。稳妥方案仍是 fixed + cover,再加一层兜底:
- 双格式
<source>:type="video/mp4"(H.264)必有,type="video/webm"(VP9)补 Firefox -
poster属性必须设,防首帧白屏;CSS 可叠加background-image: url(fallback.jpg)作最终 fallback - 真机测试不可省:模拟器无法复现 Safari 的 autoplay 策略和地址栏高度计算偏差
最易被忽略的是:视频容器的父元素如果用了 transform 或 clip-path,可能直接截断视频渲染 —— 这类样式要从视频路径上彻底剥离。



















