原生 loop 属性仅对 和 有效,必须作为布尔属性存在(如 ),赋值写法均无效;js 设置需用 videoel.loop = true,且 loop 生效依赖 muted、autoplay、playsinline(ios 必须)及用户交互,否则需用 ended 事件手动重播。

原生 loop 属性只在 <video></video> 和 <audio></audio> 上有效,且必须写成布尔属性——loop 存在即生效,赋值写法一律无效。
loop 属性怎么写才真正起作用
浏览器只检查 loop 这个属性是否存在,不读取它的值。所有带等号的写法都是错的:loop="true"、loop="1"、loop=""、loop="loop" 都不会触发循环。
- 正确写法只有:
<video loop src="bg.mp4"></video> - JS 动态设置也必须用布尔值:
videoEl.loop = true(不是"true") -
videoEl.setAttribute('loop', 'true')无效——它只是加了个 DOM 属性,videoEl.loop仍为false - 验证是否生效:执行
document.querySelector('video').loop,返回true表示属性已被识别,但不代表正在循环
为什么加了 loop 却不循环?三个最常踩的坑
loop 不是“一加就转”,它依赖视频实际进入播放状态。失效通常不是 loop 写错了,而是前提没满足。
- 没加
muted:现代浏览器(Chrome、Safari、Edge)默认阻止未静音的autoplay,视频卡在第一帧,loop 根本没机会触发 - 资源加载失败:network 面板看到
404或跨域错误,readyState停在0或1,视频压根没准备好 - 在
file://协议下双击打开 HTML:Chrome/Edge 直接禁用 autoplay 策略,即使写了autoplay muted loop也卡住
iOS Safari 上 loop 几乎不可靠,必须组合 playsinline + muted + autoplay
iOS Safari(含微信内置浏览器)对 loop 有硬性限制:仅当 muted、autoplay、playsinline 三者同时存在,且用户已触发过交互(如点击),loop 才可能激活。
-
playsinline不是可选项,是必须项——否则视频强制全屏,布局崩坏,loop 行为不可预测 - 即使静音,若播放中途因缓冲中断而“异常中止”,iOS 不会触发 loop,只响应“正常播完”
- 真机测试必不可少:模拟器常显示正常,实际设备上仍可能跳帧或卡顿
- 典型可靠写法:
<video loop muted autoplay playsinline src="bg.mp4"></video>
需要开声音或精细控制时,别硬扛 loop,改用 ended 事件手动重播
原生 loop 是声明式、零成本的,但无法干预循环时机、无法加延迟、无法换源、也无法处理播放拒绝。一旦需求超出“播完立刻重来”,就得切到 JS 控制路径。
- 监听
ended事件:video.addEventListener('ended', () => { ... }) - 重播必须两步:先
video.currentTime = 0,再调video.play();只设时间不调 play,视频不动 -
video.play()返回 Promise,iOS/Chrome 可能直接 reject,必须.catch(e => console.warn('重播被阻止:', e)) - 若用户尚未交互过,
play()会被拒绝,需引导点击后才可启用有声重播
loop 看似简单,但它的生效链条很长:属性写对 → 资源加载成功 → 播放被允许 → 播放正常结束 → 浏览器触发跳转。任意一环断掉,循环就停在半路。最容易被忽略的是“播放是否真的发生了”,而不是“loop 是否写了”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











