如何阻止Safari中视频控件触发video元素的click事件
问题原因
Safari 浏览器的原生 <video> 控件没有阻止内部点击事件向上冒泡到 video 元素本身,因此操作播放/暂停、进度条、音量等控件时,会触发绑定在 video 元素上的 click 事件。而 Chrome 内核浏览器的原生控件内部默认阻止了事件冒泡,因此不会出现该现象。
解决方案1:事件路径过滤(推荐,无侵入)
在 click 事件回调中判断事件的触发源,仅当点击的是 video 元素本身(而非内部 shadow DOM 中的控件)时,才执行自定义逻辑:
document.getElementById("videoClick") .addEventListener("click", (e) => { // 仅当事件直接触发在video元素上时执行业务逻辑 if (e.composedPath()[0] !== e.currentTarget) { return } // 这里放你原本的点击逻辑 console.log("video clicked") })
如果需要兼容低版本不支持composedPath的浏览器,可以额外补充点击位置判断作为兜底:
document.getElementById("videoClick") .addEventListener("click", (e) => { const video = e.currentTarget // 兼容判断:优先用事件路径,兜底用位置判断 const isClickControl = e.composedPath ? e.composedPath()[0] !== video : e.offsetY > video.clientHeight - 48 // 48为Safari默认控制条高度,可根据实际调整 if (isClickControl) return console.log("video clicked") })
优点
- 无需修改DOM结构,也不影响原生控件的正常使用
- 兼容所有主流浏览器,Chrome下也不会影响原有逻辑
解决方案2:自定义视频控件
如果业务需要更灵活的交互控制,可以选择隐藏原生controls属性,自己实现播放、进度条等控件,完全避免控件事件冒泡的问题:
<!-- 移除controls属性 --> <video id="videoClick" width="250"> <source src="https://example.com/media/movie.webm" type="video/webm"> <source src="https://example.com/media/movie.mp4" type="video/mp4"> 抱歉,您的浏览器不支持嵌入式视频。 </video> <!-- 自己实现控制条UI --> <div class="custom-controls"> <button id="playBtn">播放</button> <input type="range" id="progressBar"> </div>
const video = document.getElementById('videoClick') const playBtn = document.getElementById('playBtn') // 视频点击逻辑直接触发,无需过滤 video.addEventListener('click', () => console.log('video clicked')) // 自定义控件逻辑 playBtn.addEventListener('click', () => { video.paused ? video.play() : video.pause() })
优点
- 交互完全可控,不会存在浏览器兼容差异
- 可自定义控件样式,和业务UI保持统一
缺点
- 需要额外实现控件的所有功能(进度拖拽、音量调节、全屏等),开发成本较高
内容的提问来源于stack exchange,提问作者ekog
相关产品推荐
相关产品推荐

