写搜索高亮还在 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 属性只有:

  • color
  • background-color
  • text-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 不再被修改,事件绑定自然保留,迁移成本极低。

评论区

0 条评论

登录后可评论。

铁锈·Rust工具链 16 阅读