写搜索高亮还在 innerHTML.replace 包装 span?::highlight() 把这件事做进了 CSS——三个浏览器全部 Baseline 2026 支持
写搜索高亮还在 innerHTML.replace 包装 span?::highlight() 把这件事做进了 CSS——三个浏览器全部 Baseline 2026 支持。
每次在页面上实现搜索关键词高亮,标准做法是把匹配文本用 <span class="highlight"> 包起来,再加 CSS 样式。听起来简单,但每次重建高亮都要重新序列化 DOM、重新绑定事件,搜索结果更新频繁时性能损耗肉眼可见。而且 span 标签会破坏 DOM 结构,干扰辅助技术的语义判断。
CSS Custom Highlight API 第一次把这个场景做进了 CSS 层——用 JavaScript 定义文本区间,注册到 HighlightRegistry,用 ::highlight() 伪元素加样式,DOM 一行不用改。
三步上手:Range → Highlight → ::highlight()
第一步:定义要高亮的文本区间
// 从 DOM 里选出一段文本
const range = new Range();
range.setStart(document.querySelector(".content"), 0); // 起点
range.setEnd(document.querySelector(".content"), 10); // 终点(字符偏移)
第二步:注册到 CSS HighlightRegistry
// 一个 Highlight 可以包含多个 Range(用于多段匹配)
const highlight = new Highlight(range);
// 注册,名字自定义,会对应 CSS 里的 ::highlight(名字)
CSS.highlights.set("search-match", highlight);
第三步:CSS 加样式
/* ::highlight(名字) 匹配所有注册在这个名字下的文本区间 */
::highlight(search-match) {
background-color: #ffeb3b;
color: #000;
text-decoration: underline;
}
完整例子:搜索结果实时高亮
// 监听搜索框输入,动态更新高亮区间
const input = document.querySelector("input[type=search]");
const content = document.querySelector(".content");
const highlight = new Highlight();
input.addEventListener("input", (e) => {
const term = e.target.value.trim();
if (!term) {
CSS.highlights.delete("search-match");
return;
}
// 清除旧高亮
highlight.clear();
// 遍历文本找出所有匹配位置
const walker = document.createTreeWalker(content, NodeFilter.SHOW_TEXT);
let charIndex = 0;
let node;
while ((node = walker.nextNode())) {
const text = node.textContent;
let pos = 0;
while ((pos = text.indexOf(term, pos)) !== -1) {
const range = new Range();
range.setStart(node, pos);
range.setEnd(node, pos + term.length);
highlight.add(range);
pos += term.length;
}
}
CSS.highlights.set("search-match", highlight);
});
对应的 CSS:
::highlight(search-match) {
background-color: #fff176;
border-radius: 2px;
}
::highlight() 能用哪些样式
这是目前最受限制的地方。可用的 CSS 属性只有:
colorbackground-colortext-decoration及其相关属性(text-decoration-line、text-decoration-color、text-decoration-thickness)text-shadow-webkit-text-fill-color、-webkit-text-stroke-color、-webkit-text-stroke-width
background-image 会被忽略,高亮不支持渐变背景。这是和规范里其他 highlight 伪元素(::selection、::spelling-error)一致的设计。
为什么比 innerHTML.replace 更好
| innerHTML.replace | ::highlight() | |
|---|---|---|
| DOM 破坏 | 每次重建一次 | 零修改 |
| 事件绑定 | 全部丢失需重建 | 完全保留 |
| 性能 | O(n) 重建整块 DOM | 只改渲染层 |
| 语义/无障碍 | span 干扰语义 | 原 DOM 不变 |
| 清除高亮 | 重新 innerHTML | CSS.highlights.delete() |
规范与浏览器支持
CSS Custom Highlight API Module Level 1 于 2026 年 3 月随 Baseline 2026 正式进入「 Newly Available」,Chrome、Firefox、Safari 三大引擎同步支持。规范地址:https://www.w3.org/TR/css-custom-highlight-api-1/。
接下来可以做什么
把现有搜索页面的 innerHTML 高亮方案迁移过来——核心思路是把所有匹配 Range 收集进一个 Highlight 对象,CSS.highlights.set() 注册,样式用 ::highlight() 完成。DOM 不再被修改,事件绑定自然保留,迁移成本极低。
评论区
登录后可评论。