iOS Safari中video的z-index完全失效,因其被强制渲染在WebView内容层之上的原生控件层,不参与CSS层叠上下文计算;必须双写webkit-playsinline/ playsinline确保内联播放,再对video自身设置position: relative、z-index、transform: translateZ(0)和will-change: transform以触发GPU合成层。

video在iOS Safari中z-index完全失效,不是CSS写错了
这不是你的z-index设得不够大,而是iOS/iPadOS Safari把强制渲染在WebView内容层之上的“原生控件层”,它压根不参与CSS层叠上下文计算。哪怕父容器position: relative + z-index: 99999,视频照样穿透所有fixed或absolute元素。
关键前提:必须先让视频留在页面内播放,否则全屏后DOM控制权就彻底丢失了。
-
webkit-playsinline和playsinline必须双写,缺一不可;仅iOS 10+有效 - 仅加这个属性只解决“不自动全屏”,不解决层级——它只是后续hack的必要前提
- 一旦用户点击播放、系统接管全屏逻辑,所有CSS控制瞬间归零
真正起效的合成层触发组合
要让进入可被z-index管理的渲染通道,必须强制触发GPU合成层。这不是可选优化,是iOS Safari下唯一可行路径。
- 必须直接作用于
自身(不是父容器),且需同时满足:-
position: relative或absolute -
z-index(任意值,但需显式声明) -
transform: translateZ(0)或translate3d(0,0,0) will-change: transform
-
- 旧版Safari(iOS 12之前)可能还需额外加
-webkit-transform: translateZ(0) - 父容器不能有
overflow: hidden等截断合成层的行为
cover-view在小程序里能用,但别指望它干复杂活
微信/支付宝小程序中,是原生组件,CSS层级完全无效。此时cover-view是唯一合规方案,但它不是真实DOM:
- 子节点只允许
cover-image或嵌套cover-view,不能放text、button等普通组件 - 不支持
flex布局、transform、filter、background-image - 定位只认
top/left/right/bottom,单位必须是px或rpx,不支持百分比 - 事件只支持
bindtap等极少数,不支持@touchmove或自定义事件
uni-app跨端时优先走原生video标签,但必须做平台判断
在H5和App端(非nvue页面),直接用原生替换uni-app的组件,是最可控、功能不打折的解法。但必须严格守界:
- 启用条件只能是:
platform === 'h5' || (platform === 'app-plus' && !isNVue) - 小程序端完全不支持,强行使用会静默降级或报错
- 控制逻辑全部走原生API:
play()、pause()、currentTime、volume等 - 事件监听必须用
addEventListener('timeupdate', ...),@timeupdate在原生标签上不触发 - 用
ref获取DOM元素,不要依赖uni.createVideoContext
最容易被忽略的一点:所有这些方案都依赖“视频未全屏”的前提。一旦用户点击播放、系统接管全屏逻辑,所有CSS和DOM层级控制都会瞬间失效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











