z-index不生效是因为video和img不在同一层叠上下文;需检查父级是否触发新stacking context(如opacity、transform),确保定位元素同属一个上下文,必要时提升dom层级或用pointer-events控制交互。

video 和 img 重叠时 z-index 不生效?先看是否在同一个 stacking context
z-index 只对「定位元素」(position 为 relative、absolute、fixed 或 sticky)生效,且必须处于同一层叠上下文(stacking context)中才可比较。
常见错误是给 <video></video> 和 <img alt="HTML5视频与图片重叠_高频功能层级排序方法【方法" > 都加了 z-index,但父容器用了 opacity: 0.99、transform: translateZ(0) 或 will-change: transform —— 这些都会隐式创建新 stacking context,导致子元素的 z-index 在各自内部比,彼此之间不再可比。
- 确保两个元素的最近公共祖先没有触发新 stacking context
- 检查父级是否意外加了
opacity(哪怕0.99)、filter、transform、isolation: isolate - 若必须用这些属性,把需要置顶的元素(比如覆盖图层)提到更高层级的 DOM 位置,或用
position: fixed脱离原上下文
用 pointer-events 控制点击穿透,而不是删掉图层
视频播放区域常需叠加操作按钮、字幕、热区等 <img alt="HTML5视频与图片重叠_高频功能层级排序方法【方法" > 或 <div>,但又不希望它们拦截鼠标事件。此时不该靠移除 DOM 或设 <code>display: none,而应精准控制交互流:
- 给不需要响应点击的覆盖图层加
pointer-events: none - 若该图层下有按钮需响应,可在按钮上显式设
pointer-events: auto(它会继承父级none,所以必须覆盖) - 注意:
pointer-events: none对<video></video>自身也生效 —— 别误加在 video 上,否则拖拽进度条、点击暂停都会失效
移动端 video 全屏/内联播放导致图层错位?优先用 playsinline + CSS containment
iOS Safari 默认强制全屏播放 <video></video>,一旦进入全屏,所有 CSS 层叠关系重置,覆盖图层瞬间“消失”。解决不是靠 JS 监听全屏事件再重排,而是前置防御:
- 视频标签必须带
playsinline和webkit-playsinline属性 - 容器设
contain: layout paint style,防止浏览器因优化重绘而意外裁剪子元素 - 避免用
top: 50%; transform: translateY(-50%)类绝对居中——iOS 内联播放时可能触发渲染 bug,改用flex或grid布局更稳
性能敏感场景:用 will-change 换取图层提升,但别滥用
当频繁动画图层(如扫光效果、浮动 logo)与视频共存时,浏览器可能因合成策略失败导致闪烁或掉帧。此时可主动提示合成:
- 仅对真正需要独立图层的元素设
will-change: transform(或opacity) -
绝不对
<video></video>本身设will-change—— 视频解码和纹理上传已由 GPU 独立管理,加了反而干扰 - 若图层仍被降级,用 Chrome DevTools 的 Layers 面板确认是否生成了预期的 GraphicsLayer;没生成,说明触发条件不足(比如缺少
transform: translateZ(0)或opacity: 0.99)
真实项目里最常被忽略的是 stacking context 的嵌套深度——一个 opacity: 0.99 在 body 上,就能让整页所有 z-index 归零。调试时先关掉所有疑似触发属性,再逐个开,比硬调数值靠谱得多。
立即学习“前端免费学习笔记(深入)”;











