应选<p>标签而非<ul><li>,因其无默认margin、行高可控;需预排序歌词数组并用二分查找优化ontimeupdate性能;必须加will-change: transform并用requestAnimationFrame更新;LRC解析须保留毫秒级精度。

歌词 DOM 结构选
还是
用 <ul><li> 套歌词,看似语义清晰,但实际会放大同步误差:每行 <li> 的 margin、line-height 计算偏差在滚动时被累积,尤其当容器 overflow: hidden + transform: translateY() 时,1px 偏移就可能导致当前行“卡半行”。<p> 更可控——它默认无 margin,行高继承明确,配合固定 font-size 和 line-height(比如都设为 1.5),能保证每行高度严格一致。若必须用列表,得手动重置:ul { margin: 0; padding: 0; } li { margin: 0; line-height: 1.5; }。
ontimeupdate 触发太密,直接遍历歌词数组会掉帧
浏览器每秒可能触发 4–6 次 ontimeupdate,而歌词数组常有 50+ 条。每次都在里面 for 或 forEach 查找当前时间对应索引,CPU 负担大,且容易因 JS 执行延迟错过关键帧。正确做法是:预排序 + 二分查找。确保 lrcArray 按 t 升序排列后,用 findIndex 改写为二分逻辑(时间复杂度从 O(n) 降到 O(log n))。更进一步,可缓存上一次找到的索引,下一次先比对相邻 1–2 行,多数情况免去全量搜索。
用 translateY 滚动时,will-change: transform 不是可选项
没加 will-change: transform 的 <ul> 在高频 translateY 下,Chrome 会频繁触发合成层重建,导致滚动卡顿、歌词“抖动”。这不是 CSS 写法问题,而是渲染管线没提前获知变换意图。必须显式声明:.lyricsList { will-change: transform; }。同时注意:别对整个歌词容器设 position: absolute 后再动 top——这会强制重排,性能远差于 transform。另外,requestAnimationFrame 包裹偏移更新是底线,不能直接在 ontimeupdate 里改样式。
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
LRC 解析时忽略毫秒位,会导致前几秒完全不同步
LRC 时间戳是 [mm:ss.xxx] 格式,比如 [01:23.456]。很多解析代码只取到秒级:parseInt(secPart),把 .456 截掉了。结果就是所有歌词整体延后最多 999ms,开头几秒完全错位。正确解法是统一转成毫秒:const totalMs = min * 60000 + sec * 1000 + ms,然后在比对时用 audio.currentTime * 1000 对齐。还要注意:有些 LRC 文件用 . 也有用 , 分隔毫秒,得兼容处理,否则 parseFloat('23,456') 返回 23。
立即学习“前端免费学习笔记(深入)”;
真正难的不是让某句歌词“亮起来”,而是让整套机制在低端安卓机、旧版 Safari、甚至 Electron 封装的桌面端里,都保持 100ms 内响应。时间戳精度、DOM 批量操作、GPU 合成策略,三者缺一不可——漏掉任意一个,用户听到的就是“歌词慢半拍”。


















