poster在safari中需preload="metadata"才加载,chrome中loadedmetadata后立即消失,须js接管显示;ios可能完全忽略,需兜底灰图或覆盖层方案。

HTML video 的 poster 属性在 Safari(尤其是 iOS 15+)、旧版 Android WebView 和部分桌面浏览器中“设了却看不见”,不是写错了,而是它根本没被加载或刚加载完就被移除了——必须按浏览器实际行为来干预,不能只靠写死属性。
为什么 poster 在 Safari 里完全不请求图片?
Safari(macOS Monterey / iOS 15+)默认对 poster 实施懒加载:若未显式声明 preload="metadata",它连 HTTP 请求都不会发,直接跳过渲染阶段。这不是路径问题,是策略性忽略。
- 必须同时满足三项:
preload="metadata"+ 去掉autoplay+poster值为同源绝对或相对路径(如"/assets/cover.jpg") - 禁用
file://协议测试:Safari 下双击 HTML 文件必失效,必须起本地服务(如python3 -m http.server) - 不要用
.webp或data:URL:poster不支持 WebP(iOS 16 前全不认),base64 会静默 404
Chrome/Edge 里 poster “一闪就消失”怎么拦住?
Chrome v78+ 在 loadedmetadata 事件一触发就丢弃 poster,哪怕视频还没播放、用户手指都还没动——这是设计,不是 bug。想让它撑到点击,得用 JS 主动接管显示逻辑。
- 给
video加内联背景:style="background: url(cover.jpg) center/cover no-repeat;",作为底层兜底 - 监听
loadedmetadata后,动态插入一个<img>覆盖层(position: absolute,z-index高于video) - 再监听
play或timeupdate(首帧渲染后)移除该<img>,避免遮挡控件 - 别用
::before伪元素:<video></video>上绝大多数浏览器不支持
动态换 poster 为什么赋值无效?
直接写 videoEl.poster = "new.jpg" 在 iOS Safari 和多数 WebView 中静默失败——浏览器不触发重绘,也不重新发起请求。
- 正确做法:先改
poster,再立刻调videoEl.load()强制刷新资源状态 - 注意副作用:
load()会清空已缓冲的视频数据,正在播放中慎用 - 若用
URL.createObjectURL(blob)生成 poster,替换后必须跟URL.revokeObjectURL()防内存泄漏 - 服务端返回的 poster URL 必须带 CORS 头(
Access-Control-Allow-Origin: *),否则 iOS Safari 静默拒绝
iOS Safari 兜底方案不能省
即使所有配置都对,某些 iOS Safari 版本(如 iOS 15.6、16.4)仍会彻底忽略 poster——这不是你漏了什么,是 Apple 没实现。这时候没有通用修复,只有两个务实选择:
- 用一张 1×1 像素灰图(PNG)作为保底
poster,至少避免黑屏 - 完全绕过原生机制:
<div class="video-wrapper"> <video></video><img class="poster-overlay" src="cover.jpg"> </div>,初始display: block,监听playing后display: none
真正难的不是让 poster 显示出来,而是在不同缓存状态、网络延迟、系统版本下,始终知道它当前处于哪个加载阶段,并主动干预——这意味着你要把它当做一个需要轮询和监听的状态,而不是一个静态属性。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











