poster生效需同时满足:①src存在且可访问;②preload设为"metadata";③poster图片url返回200及正确content-type;ios safari和微信中还需控制图片≤150kb并监听loadedmetadata兜底。

poster 属性生效的三个硬性前提
poster 不是“写了就显示”的装饰属性,它依赖浏览器对视频元数据的加载流程。只有同时满足以下三点,poster 才可能真正渲染出来:
-
src必须存在且可访问:空字符串、null、404 或跨域拒绝都会让 poster 彻底静默 -
preload必须设为"metadata":这是触发 poster 渲染的关键开关;"auto"可能跳过 poster 直接解码首帧,"none"则完全不请求元数据 - 图片 URL 必须返回 200 + 正确
Content-Type(如image/jpeg):路径写错、服务端返回 403/500、或 MIME 类型错误(比如返回text/plain)时,浏览器既不报错也不 fallback,只留空白
为什么 iOS Safari 和微信里 poster 经常不出现
iOS Safari(15–16)和微信内置 WebView 对 poster 有懒加载策略:若未显式设置 preload="metadata",且 poster 图片体积 >200KB,浏览器会直接跳过请求这张图——不是卡住,是根本不去 fetch。
更隐蔽的问题是:微信中若用 background-image 模拟 poster,会拦截 click 事件,导致点击视频区域无法触发播放。
解决方案很直接:
- 强制加
preload="metadata",哪怕你后续要手动控制播放 - poster 图控制在 150KB 以内,用 WebP 格式优先
- 监听
loadedmetadata事件,在回调里做兜底逻辑(比如手动显示一个覆盖层)
播放结束后如何“恢复”封面效果
poster 只在加载阶段起作用,播放结束(ended 事件)后它不会自动回来。这不是 bug,是规范行为。
要实现“播完回封面”,必须手动接管:
- 监听
ended事件,然后调用load()方法重载视频 —— 这会触发 poster 再次显示,但代价是重新请求元数据,有延迟 - 更轻量的做法:用 CSS 遮罩层 +
visibility: hidden控制 video 元素,在ended时显示遮罩层并还原 poster 图(注意保持宽高比一致) - 避免用
display: none切换 video,会导致某些 Android 设备音轨残留或全屏异常
常见误操作:用 background-image 替代 poster
虽然加个 div 包住 video 并设背景图看起来一样,但它破坏了原生语义和交互:
- 全屏时只放大
video元素,背景图被裁切或错位 - 进度条、音量控件的热区偏移,尤其横竖屏切换后定位失准
- iOS 微信中,背景图层会捕获所有点击,
video失去点击响应能力 - 无法通过 JS 获取原生 poster 的宽高信息,影响响应式适配
真正难的不是写对 poster="/assets/cover.jpg",而是理解它嵌在浏览器媒体加载管线里的位置——它不是 UI 层的“封面”,而是元数据加载流水线中的一个视觉锚点。一旦加载流程被绕过(比如 preload 被覆盖、src 动态绑定为空),它就彻底失效,且无任何提示。











