必须显式设置样式才能让mark标签稳定生效,因默认黄色背景在高对比度模式、Outlook邮件客户端及CSS重置规则下常失效;需同时声明background-color和color,加padding和border-radius,并适配深色模式与WCAG对比度标准。

mark 标签本身不保证高亮可见,必须显式设置样式才能在真实环境中稳定生效。
为什么直接写 文本 经常没反应
浏览器默认的黄色背景在三种常见场景下会完全失效:Windows 高对比度模式 强制清空背景色;Outlook 邮件客户端 忽略所有 UA 样式;项目中用了 * { background: transparent } 这类 CSS 重置规则。此时文字可能变成黑底黑字甚至完全不可读。
必须同时声明 background-color 和 color,否则在禁用 UA 样式的环境里文字可能消失。只写 background: none 是错的——它不会清除 background-image,应写 background-color: transparent。
- 加
padding: 2px 4px和border-radius: 3px是刚需,原生mark紧贴文字,边缘生硬易误读 - 深色模式下必须手动适配:
@media (prefers-color-scheme: dark) { mark { background-color: #37414f; color: #f9fafb; } } - 颜色对比度必须满足 WCAG AA 标准(至少 4.5:1),比如
#e53e3e配white可行,但#ffcc00配black不行
动态搜索高亮必须遍历文本节点,不能碰 innerHTML
直接 el.innerHTML = el.innerHTML.replace(...) 会触发三类严重问题:用户搜 a.b?c 未转义正则元字符 → 报错中断;搜 <script>alert(1)</script> → XSS;原文含 → 替换后撕开标签,DOM 解析失败。console.log()
正确做法是只操作纯文本节点:
- 用
document.createTreeWalker(element, NodeFilter.SHOW_TEXT)获取全部文本节点 - 对每个节点的
textContent做匹配,关键词先双重转义:keyword.replace(/[&"'`=/]/g, c => `${c.charCodeAt(0)};`)(HTML 转义)+.replace(/[.*+?^${}()|[]]/g, '\$&')(正则转义) - 匹配后创建新节点:
const mark = document.createElement('mark'); mark.textContent = match;,再用node.parentNode.replaceChild(mark, node)
多关键词高亮要按长度降序处理,否则语义断裂
同时高亮 "JavaScript" 和 "Script" 时,若先匹配短词,会导致 JavaScript 这类非法嵌套。浏览器虽自动修正为两个独立 mark,但语义已断裂、CSS 样式错位。
正确顺序是提取所有关键词后排序:Object.keys(tagColors).sort((a, b) => b.length - a.length)。这样 "JavaScript" 优先于 "Script" 匹配,避免内部被二次切割。
如果关键词来自用户输入或服务端,注意过滤空字符串和重复项,否则会生成冗余或空 节点,影响可访问性和渲染性能。
真正容易被忽略的是:高亮不是“加个黄底”就完事,而是涉及可访问性、安全、语义和跨环境兼容性的综合判断。哪怕只改一行样式,也要同步检查深色模式、高对比度系统、邮件客户端和屏幕阅读器行为。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











