::highlight() 需配合 JS 创建 Highlight 实例并绑定唯一 name,CSS 变量必须通过宿主元素内联 style 或属性选择器显式传递,无法继承;Chrome/Edge 120+ 支持,Firefox/Safari 需降级为 mark 或 span。

用 ::highlight() 配合 CSS 变量动态改高亮色
原生 CSS 高亮 API(::highlight())目前只在 Chromium 120+(含 Edge、Chrome)中可用,且必须配合 document.highlightRange() 或 document.createHighlight() 使用。纯 CSS 无法直接“选中任意文字并高亮”,所以所谓“多段文字高亮”,本质是 JS 创建多个 Highlight 对象,再用 CSS 变量控制各自颜色。
常见错误是写成这样:::highlight(my-highlight) { background-color: var(--hl-color); },然后以为改 --hl-color 就能批量变色——不行。每个 ::highlight(x) 是独立伪元素,变量必须作用于其宿主选择器或内联 style 才生效。
- 正确做法:给每个
Highlight对象绑定唯一 ID(如"hl-1"、"hl-2"),再为每个 ID 单独写::highlight(hl-1)规则,或统一用[data-hl-id]属性选择器 +style内联变量 - 若想复用样式,推荐用属性选择器 +
style设置变量:[data-hl-id="hl-1"]::highlight(hl-1) { background-color: var(--color); },然后 JS 动态设el.style.setProperty('--color', '#ff9e00') - 注意:CSS 变量不能直接在
::highlight()里被继承,必须显式传入;父元素的--color不会自动落到::highlight()上
JS 创建多段 Highlight 并关联 CSS 变量
核心是把每段文本范围转成 Range,再塞进 Highlight 实例,最后注册到 document.anchors。变量控制靠的是给宿主元素加 data 属性或内联 style,再让对应 ::highlight() 规则读取它。
典型场景:搜索关键词高亮、代码语法标记、协作编辑中的多人标注。
立即学习“前端免费学习笔记(深入)”;
- 创建 Highlight 实例时,用
new Highlight(range1, range2, ...)支持多段,但所有段共享同一套样式(即同一个::highlight(x)规则) - 要实现“每段不同色”,就得为每组范围新建一个
Highlight实例,并分配不同 name(如hl-user-1、hl-user-2) - 注册后,JS 可随时调用
highlight.setRanges([newRange1, newRange2])更新位置,但 color 必须靠重设 CSS 变量或切换规则
const range1 = document.createRange();
range1.selectNodeContents(document.querySelector('.text').childNodes[0]);
const hl1 = new Highlight(range1);
hl1.name = 'hl-1';
document.anchors.set('hl-1', hl1);
// 然后在 CSS 里写:
// ::highlight(hl-1) { background-color: var(--hl-1-color, #ffcc00); }
// 再用 JS 控制:document.documentElement.style.setProperty('--hl-1-color', '#00aaff');
::highlight() 的兼容性与 fallback 处理
Firefox 和 Safari 完全不支持 ::highlight(),连前缀版都没有。生产环境必须降级:用 <mark> 包裹或插入带 class 的 <span>。
容易踩的坑是只检测 CSS.supports('selector(::highlight)'),这在旧 Chrome 里也返回 true,但实际无效——得结合 typeof Highlight !== 'undefined' 和 'set' in document.anchors 双重判断。
- 不要依赖
CSS.supports('background-color: highlight')——这是错的,highlight不是颜色值 - fallback 方案建议用
data-highlight-id统一标记 DOM 节点,JS 初始化时根据支持与否决定走 native highlight 还是 DOM 插入 - 性能影响:大量
Highlight实例(>50)可能触发重排卡顿,尤其在频繁更新 range 时;建议做节流或合并相邻 range
为什么不用 mark 标签代替?
<mark> 简单可靠,但破坏语义、干扰屏幕阅读器、无法跨节点高亮(比如跨 <p> 和 <em> 的连续文字),且样式控制粒度粗(所有 <mark> 共享同一 class)。
而 ::highlight() 是 presentation-only,不改变 DOM 结构,支持跨节点、可编程更新、样式完全解耦——前提是接受它的实验性和浏览器限制。
- 如果你只需要静态高亮几处,
<mark>更轻量、更稳 - 如果你要做实时搜索高亮、协作标注、或需要精确控制每段颜色/透明度/动画,
::highlight()是目前唯一原生方案 - 别忘了:
Highlight实例不会随 DOM 删除自动销毁,需手动document.anchors.delete('name'),否则内存泄漏
mark 模拟、Safari 的 span 注入,而且每套对 range 边界、换行、空格的处理都不一样。


















