controls属性用于启用浏览器原生视频控件,不接受任何值,拼写错误或缺失即失效;其显示受src路径、preload设置、CSS隐藏、Shadow DOM隔离及iOS playsinline缺失等五因素影响。

controls 属性就是让浏览器画出那一排原生控件:播放/暂停按钮、进度条、音量滑块、全屏按钮、字幕开关(如果视频带字幕轨道)——写上就出现,不写就没有。
它不接受值,不是 controls="true",也不是 controls=""(后者虽能生效,但多余);拼错成 control(少个 s)就完全失效。
controls 不显示?先查这五件事
-
src路径 404 或返回了错误 MIME 类型(比如服务器把.mp4当作text/plain发送) -
preload="none"且视频尚未开始加载,Safari 可能等元数据加载完才渲染控件 - CSS 里写了
display: none、visibility: hidden或opacity: 0,整个<video>元素不可见 - 在 Shadow DOM 或自定义 Web Component 里使用时,样式隔离导致控件区域被裁剪或未渲染
- iOS Safari 下没加
playsinline,且用户还没点过屏幕——控件可能“存在但不可见”,DOM 里有,视觉上却空着
controlslist 不是 controls 的替代品
controlslist 必须和 controls 一起用才有效,它只负责删减按钮,不能开启或关闭控件本身:
-
controlslist="nodownload nofullscreen"→ 下载和全屏按钮消失,其他照常 -
controlslist="noremoteplayback"→ 投屏按钮隐藏(Chromecast / AirPlay 场景) - Firefox 基本忽略所有
controlslist值(截至 v128) - iOS Safari 16.4+ 才开始支持
nofullscreen,安卓 WebView 中nodownload多数无效
想彻底定制 UI?必须关掉 controls
只要 controls 属性存在,浏览器就会强制渲染原生控件,CSS 伪元素(如 ::-webkit-media-controls)在多数新版本浏览器中已被禁用或不可靠。
立即学习“前端免费学习笔记(深入)”;
真正可控的做法是:
- 移除
controls属性 - 监听
loadedmetadata事件确保元数据就绪 - 用
video.play()、video.pause()、video.currentTime、video.volume等 API 实现逻辑 - 自己画按钮、进度条(比如用
<input type="range">绑定currentTime) - 注意移动端限制:iOS 需
autoplay muted playsinline或用户首次交互后才能触发有声播放
最常被忽略的一点:控件是否“可操作”,跟 controls 是否存在无关。它只决定“画不画出来”,而资源加载失败、CORS 拦截、MIME 错误、iOS 手势策略,都会让控件变成摆设——看着在,点不了,拖不动。



















