弹幕层必须与video同级且共用父容器,设position: absolute并pointer-events: none;避免祖先元素创建堆叠上下文;大量弹幕须用canvas渲染并动态同步尺寸;移动端交互需canvas hit-test替代DOM事件。

弹幕层必须是 video 的同级兄弟元素,不能嵌套在 video 内部
浏览器会忽略所有放在 <video> 标签内部的非媒体子元素(比如 <div class="danmaku">),即使加了 position: absolute 也压不上去。正确结构是让弹幕容器和 video 共享同一个父容器,并用定位叠在一起:
<div class="video-wrapper"> <video src="demo.mp4" controls></video> <div class="danmaku-layer"></div> </div>
对应 CSS 必须确保:
-
.video-wrapper设为position: relative -
.danmaku-layer设为position: absolute; top: 0; left: 0; width: 100%; height: 100% -
.danmaku-layer的pointer-events: none(否则会拦截视频点击事件)
z-index 失效的常见原因:父元素堆叠上下文干扰
即使给 .danmaku-layer 设置了很高的 z-index,如果它的某个祖先元素(比如 .video-wrapper)有 transform、opacity < 1 或 will-change,就会创建新的堆叠上下文,导致弹幕被“关”在这个局部层级里,永远盖不住 video。
排查方法:打开开发者工具,选中弹幕层,看「Computed」面板里「Stacking Context」是否显示「Yes」;如果是,就得往上逐级检查样式。最稳妥的解法是:
立即学习“前端免费学习笔记(深入)”;
- 移除
.video-wrapper上所有可能触发新堆叠上下文的属性 - 改用
isolation: isolate替代transform做布局(如需居中等) - 确认
video自身没有设置z-index(它默认是 auto,无法被 z-index 控制)
弹幕文字渲染要用 canvas,别用 div + position: absolute
大量弹幕同时运动时,用 DOM 元素逐个定位会导致严重卡顿——每个弹幕 div 都触发重排重绘,100 条就可能掉帧。实际项目中必须用 canvas 绘制:
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
- 把弹幕文本缓存为
canvas.textMetrics或预渲染成 bitmap - 用
requestAnimationFrame统一更新坐标并清空重绘,避免 layout thrashing - 注意
canvas尺寸要随video的clientWidth/clientHeight动态同步,不能只靠 CSS 缩放
示例关键逻辑:
const canvas = document.querySelector('.danmaku-layer canvas');<br>const ctx = canvas.getContext('2d');<br>function resize() {<br> const video = document.querySelector('video');<br> canvas.width = video.clientWidth;<br> canvas.height = video.clientHeight;<br>}<br>window.addEventListener('resize', resize);
移动端触摸穿透问题:弹幕层必须设 pointer-events: none,但交互弹幕除外
默认情况下,覆盖在 video 上的弹幕层会吞掉所有 touch/click 事件,导致进度条拖动、全屏按钮失效。全局关闭即可:
.danmaku-layer { pointer-events: none; }
但如果要做「点击弹幕跳转时间点」这类功能,就不能全关。可行方案是:
- 只对普通滚动弹幕关闭
pointer-events - 对可交互弹幕(如带
data-timestamp的)单独用<span>包裹,并设pointer-events: auto - 监听弹幕层的
click事件,用document.elementFromPoint(x, y)反查是否点中了可交互弹幕
记住:iOS Safari 对 pointer-events: none 在 canvas 上的支持不稳定,真要交互,优先用 canvas 自己做 hit-test,别依赖 DOM 事件冒泡。


















