playsinline 失效是因为未满足 iOS Safari 的多重校验条件:必须同时设置 playsinline 和 webkit-playsinline,且需 muted、autoplay、controls="false" 等配套属性齐全,微信还需 x5-video-player-type="h5-page" 等专有属性,并避免 transform 等布局异常。

为什么加了 playsinline 还是全屏?
不是属性没生效,而是它根本没被“受理”——playsinline 在 iOS Safari 里是一张入场券,不是通行证。漏掉任一配套条件,浏览器直接跳过校验,fallback 到全屏播放器。
-
webkit-playsinline没一起写:iOS 9–14.8 会完全忽略playsinline,必须两个属性同时存在 -
muted缺失:有声视频在无用户手势时根本播不起来,playsinline压根没机会触发 -
autoplay没配:即使用户点了播放,首次触发若没autoplay+muted,Safari 可能判定为“非可信上下文”而强制全屏 -
controls="false"没显式声明:省略controls或设为false但没用 CSS 隐藏,某些 iOS 17 设备会检测到“控件不可见”而主动降级
playsinline 和 webkit-playsinline 必须同时出现
这不是可选组合,是 iOS 兼容性兜底的硬性要求:前者是 HTML5 标准属性(iOS 10+ 支持),后者是 WebKit 私有属性(iOS 9–10.3 仅认这个)。拼写错误、赋值写法(如 playsinline="true" 或 webkit-playsinline="true")都会失效。
- React 中写
playsInline(PascalCase)会被自动转成小写playsinline,但前提是它在首次 render 就存在,不能等useEffect里补 - Vue 中用
v-bind:playsinline="true",若绑定值为false或null,该属性根本不会出现在最终 DOM 上 - JS 动态
setAttribute('playsinline', '')或setAttribute('webkit-playsinline', '')在 iOS Safari 中完全不生效
微信 iOS 客户端要额外加 x5-video-player-type="h5-page"
微信 iOS 用的是 X5 内核,不认纯标准属性。漏掉 x5-video-player-type="h5-page",大概率还是 fallback 到自己的全屏播放器;加了但没配 x5-video-orientation="portrait",可能被横屏劫持。
- 安卓微信只认
x5-playsinline="true",playsinline和webkit-playsinline对它基本无效 -
x5-video-player-type="h5-page"在 m3u8 直播流场景下反而会强制全屏,此时应去掉,改用x-webkit-airplay="allow"+x5-playsinline="true" - 微信中若用
video.src动态加载,必须调video.load()再video.play(),否则 Safari 不重新校验内联策略
CSS 布局异常会让 playsinline 形同虚设
iOS Safari 会对容器做隐式健康检查,哪怕所有 HTML 属性都写对了,一个 transform 就能让整套策略崩盘。
- 父容器用了
transform(如scale(0.9)、translateZ(0)、perspective):部分 iOS 16+ 设备会认为“渲染上下文不稳定”,强制全屏 - 父容器设了
overflow: hidden:可能截断内联视频层,建议设为visible或用clip-path替代 -
object-fit: cover但宽高比不匹配:Safari 可能判定“布局异常”而 fallback 全屏
<video src="clip.mp4" muted autoplay loop playsinline webkit-playsinline x5-video-player-type="h5-page" x5-video-orientation="portrait" x-webkit-airplay="allow" controls="false"></video>
最易被忽略的不是属性缺不缺,而是 JS 调用 play() 的那一瞬间——是否还在用户手势上下文中。

















