原生 loop 属性需作为布尔属性直接写在 video 标签中,如 ;js 控制应赋布尔值 video.loop = true/false 并配合 load() 刷新状态;ios 限制严格,需 muted autoplay 才可能生效。

video 标签加 loop 属性就能循环,但得加对位置
html5 的 <video></video> 元素原生支持循环,关键不是写 JS,而是把 loop 当作布尔属性直接写在标签里。它没有值,写成 loop="true" 或 loop="false" 都无效——浏览器只认有没有这个属性本身。
常见错误是把它当普通属性处理,比如动态用 JS 设置 video.loop = "true"(字符串),其实应该赋布尔值:video.loop = true。
-
<video loop></video>—— 正确,静态启用循环 -
<video loop="loop"></video>—— 也行,但冗余,不推荐 -
<video loop="true"></video>—— 失效,浏览器忽略值,只看是否存在该属性 - JS 中写
video.setAttribute('loop', 'true')—— 同样失效,应改用video.loop = true
取消循环不能只删 HTML 属性,JS 控制要同步
如果页面加载后通过 JS 动态关掉循环,光靠 removeAttribute('loop') 不一定立刻生效,尤其在 chrome 和 safari 中可能有延迟或状态残留。更可靠的做法是显式设为 false 并触发一次 load() 或重置播放状态。
- 启用循环:
video.loop = true - 关闭循环:
video.loop = false,然后建议跟一句video.load()确保状态刷新 - 不要只依赖
removeAttribute('loop'),它不改变 JS 层的loop属性值 - 若视频正在播放中关闭循环,当前循环不会中断,要等本周期结束才停;想立刻停止,需配合
pause()和currentTime = 0
移动端 iOS Safari 对 loop 有硬性限制
iOS 上的 Safari(包括微信内置浏览器)默认禁用自动播放和循环,哪怕写了 loop 且用户已交互过,也可能被静音策略连带抑制循环行为。这不是 bug,是 Apple 的策略:防止无感循环消耗资源或干扰体验。
立即学习“前端免费学习笔记(深入)”;
- 必须配合
muted和autoplay才可能让loop在 iOS 生效(例如背景视频) -
<video loop muted autoplay></video>是 iOS 上最接近“真正循环”的组合 - 如果视频需要声音,iOS 下基本无法可靠实现自动循环,得用 JS 监听
ended事件手动重播 - android 浏览器一般没这限制,但部分定制 ROM 可能模仿 iOS 行为
用 JS 监听 ended 事件手动循环更可控,但也更重
绕过原生 loop 的限制时,监听 ended 事件 + currentTime = 0 + play() 是通用解法,但它会引入短暂停顿、触发额外的 promise 拒绝(尤其在静音未开时),还可能被浏览器防打扰策略拦截。
- 基础写法:
video.addEventListener('ended', () => { video.currentTime = 0; video.play(); }); - 必须处理
play()返回的 Promise,否则控制台报错:video.play().catch(e => console.warn('play failed:', e)); - 如果视频是
muted,成功率高;否则在多数现代浏览器中会失败 - 重复调用
play()可能导致音频卡顿或时间轴跳变,不如原生loop流畅
原生 loop 是最轻量的方案,但它的生效条件比看起来更“娇气”——尤其是跨平台时,iOS 的限制、静音状态、是否用户触发过交互,都会让它悄悄失效。别只盯着属性写没写对,得查它实际有没有被浏览器采纳。