必须使用<mark>实现搜索关键词高亮,因其具备语义可访问性、读屏器明确播报、搜索引擎结构化提取等不可替代优势;禁用<span class="highlight">,避免嵌套、XSS及中文分词误匹配等问题。

搜索关键词高亮必须用 <mark>,不是视觉选择而是语义刚需
辅助技术(如读屏器)会把 <mark> 明确读作“高亮文本”,而 <span class="highlight"> 默认无声无息;搜索引擎也可能单独提取 <mark> 内容用于摘要或片段生成。如果你在搜索页返回的 HTML 里用 span 替代 <mark>,等于主动放弃语义层的可访问性与结构化能力。
常见错误现象:
- 用户搜 “React”,页面渲染出
<span class="hl">React</span>→ 读屏器不提示“这是匹配词”,盲人用户无法感知搜索命中 - 服务端返回已带
<mark>的 HTML,但前端 JS 又用正则二次包裹 → 出现<mark><mark>React</mark></mark>,嵌套破坏语义且 CSS 难控制
动态插入 <mark> 时,innerHTML 是最危险的写法
用户输入的关键词(比如来自 URL 的 q=JS<script>>)若未经转义直接拼进字符串再赋给 <code>innerHTML,会触发 XSS,且可能因 &、< 等字符导致 DOM 解析中断。
安全做法是绕过字符串拼接,用原生 DOM 方法组装:
立即学习“前端免费学习笔记(深入)”;
- 用
textContent创建纯文本节点(自动转义) - 用
document.createElement('mark')创建标记节点 - 用
appendChild()或insertAdjacentElement()插入,而非innerHTML += '...' - 若必须用正则替换,先对 keyword 调用
escapeHtml(keyword)(转义&、"、'、`、<、=、/)
示例关键逻辑:
function highlightText(node, keyword) {
const escapedKeyword = escapeHtml(keyword);
const parts = node.textContent.split(new RegExp(`(${escapedKeyword})`, 'gi'));
while (node.firstChild) node.removeChild(node.firstChild);
parts.forEach(part => {
if (part.toLowerCase() === keyword.toLowerCase()) {
const mark = document.createElement('mark');
mark.textContent = part;
node.appendChild(mark);
} else {
node.appendChild(document.createTextNode(part));
}
});
}
<mark> 的样式不能只靠浏览器默认值交付
旧版 Safari 忽略 <mark> 默认背景;Windows 高对比度模式下黄色背景可能被强制重置为纯黑;深色主题中默认黄底黑字对比度不足(AA 级别不达标)。
生产环境必须显式声明至少三项:
-
background-color(不能只写background: none,会漏掉background-image) -
color(尤其暗色背景下要手动设深色文字) -
padding(默认无内边距,文字贴边易糊,建议0.1em 0.25em)
推荐基础样式:
mark {
background-color: #ffeb3b;
color: #212121;
padding: 0.1em 0.25em;
border-radius: 2px;
}
中文搜索高亮要小心全角/半角和词边界问题
英文可用 锚定单词边界,但中文没有天然分词边界。直接用 /keyword/g 替换,容易出现“教育”被拆成“教育”或“教育部”误标为“教育部”。
更稳妥的做法是:
- 避免用正则全局替换,改用
String.prototype.indexOf()手动查找位置,再逐段切分 - 对中文关键词做前后空格/标点检查(如匹配前加
(^|\s|[,。!?;:""'()【】《》])) - 服务端高亮优先:由后端按分词结果返回已包裹的 HTML,前端只负责渲染,不参与匹配逻辑
- 若必须前端分词,引入轻量级中文分词库(如
segmentit),而非依赖简单字符串包含判断
真正麻烦的从来不是怎么写那行 <mark>xxx</mark>,而是决定“xxx”是否真的构成一个语义完整的匹配单元——尤其在中英文混排、数字缩写、大小写敏感等场景下,机器分词和人工直觉常不一致。



















