poster加载慢本质是请求时机错误,应通过intersectionobserver监听视口后设置、避免提前赋值、使用webp+70质量+匹配宽高比、预校验加载、动态替换时调用load()、ssr内联保底、必须设preload="metadata"。

poster 图片加载慢,本质是请求时机错了
写死 poster="cover.jpg" 会让 Safari 等浏览器在 HTML 解析阶段就发起请求,哪怕视频还在屏幕外、用户根本没滚动过去。这不是图片本身慢,而是“不该发的时候发了”,挤占首屏关键资源队列。
- 用
IntersectionObserver监听进入视口后再设置:videoEl.setAttribute('poster', 'thumb-720p.webp') - 对默认不自动播放的视频,干脆初始不设
poster,等用户 hover 播放按钮或点击时再注入 - 避免给
display: none或visibility: hidden的<video></video>提前赋值,旧版浏览器仍可能触发加载
WebP + 70 质量 + 匹配宽高比,不是建议,是硬门槛
一张 1280×720 的 WebP 图,质量设为 70,体积通常压到 40 KB 左右——刚好低于 iOS Safari 对 poster 的敏感阈值(200 KB),又足够撑起 LCP。尺寸不匹配宽高比(比如视频是 16:9 却塞个 4:3 图),浏览器会缩放,导致模糊或重绘。
- 必须用 WebP:Chrome/Firefox/Safari 16.4+ 全支持;iOS Safari 14+ 也兼容;fallback 到 JPEG,别用 PNG(体积大)
- 质量别贪高:65–75% 是清晰度与体积的最优平衡点,100% 质量 WebP 可能超 150 KB,反而触发 iOS 懒加载
- 宽高比必须一致:16:9 视频就用 1280×720 或 640×360,别靠 CSS
object-fit补救
加载失败不报错,得自己预校验
poster 加载失败不会触发 <video></video> 的 error 事件,监听 video.onerror 完全无效。白屏发生时,你根本不知道图挂了。
- 用
new Image()预加载:img.onload = () => videoEl.poster = url; img.onerror = () => fallbackToBase64OrColor() - 动态换封面时,不能只改
videoEl.poster = 'new.jpg',要先videoEl.removeAttribute('poster'),再setAttribute,最后调videoEl.load()强制刷新(注意:会清空已缓冲的视频数据) - SSR 场景下,服务端可提前校验路径有效性,或内联一个极简 data URL 作为保底封面(如
poster="data:image/png,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==")
不加 preload="metadata",iOS Safari 就当 poster 不存在
iOS Safari(尤其 15–16)有个经典行为:不设 preload="metadata",它就把 poster 当作非关键资源,根本不发请求——直到用户点播放才闪一下。这不是 bug,是策略。
- 必须显式写
preload="metadata"(不是"auto",后者会预加载整个视频流) - 确保
<video></video>有controls和playsinline,否则移动端控件可能不渲染,连带poster失效 - 本地开发务必起服务(如
python3 -m http.server),直接双击 HTML 文件协议下poster会因跨域被静默拦截
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











