<mark>标签最安全语义正确,专用于强调与当前场景强相关的文本,需手动写CSS适配暗色模式与可访问性,JS高亮应操作文本节点而非innerHTML,优先用Range API处理选区。

直接用 <mark> 标签最安全也最语义正确
不用 JS、不拼字符串、不改 innerHTML,就能立刻生效。浏览器默认给 <mark> 加黄色背景,屏幕阅读器会读作“marked text”,搜索引擎也认得这是上下文相关高亮——它不是装饰,是语义声明。
常见错误是把它当 <span class="highlight"> 用:比如包裹整段 <p>,或嵌套在 <strong> 里再套一层 <mark>。这会破坏语义层级,且旧版 Safari 可能让子元素颜色被覆盖。
- 只用于真实需要强调“与当前场景强相关”的文本,比如搜索关键词、引用匹配项
- 别包裹块级元素(
<p>、<div>),只包纯文本或行内元素(<em>、<code>) - 若需兼容 IE8 及更早版本,必须退回到
<span role="mark">+ 手动加 CSS,但实际项目中基本可忽略
用 JS 做搜索高亮时,必须避开 innerHTML.replace()
用户搜 [a-z] 或 <script>alert(1)</script>,直接塞进正则或字符串拼接,轻则脚本报错中断,重则触发 XSS,还会把 <code>console.log()</code> 撕成 <code>console.<mark>log</mark>()</code>,DOM 直接解析失败。
正确路径是只操作文本节点:用 document.createTreeWalker(element, NodeFilter.SHOW_TEXT) 遍历,跳过空节点(node.textContent.trim() === ''),对每个节点内容做正则匹配,然后创建 <mark> 元素插入 DOM。
立即学习“前端免费学习笔记(深入)”;
- 正则转义不能少:
keyword.replace(/[.*+?^${}()|[]\]/g, '\$&') - HTML 实体也要转:
keyword.replace(/[&"'`=/]/g, c => `${c.charCodeAt(0)};`) - 中文关键词记得加
u标志:new RegExp(pattern, 'giu') - 替换必须用函数回调:
str.replace(regex, (match) => { const mark = document.createElement('mark'); mark.textContent = match; return mark; }),别用'<mark>$&</mark>'字符串形式
<mark> 的样式必须手动写,别信浏览器默认值
默认黄色背景在暗色模式下几乎不可见,Windows 高对比度设置会强制设为纯黑,Outlook 邮件客户端完全忽略 UA 样式,某些 CSS 重置规则(如 * { background: transparent })还会清掉默认背景。不写 CSS 就上线,等于放弃可访问性。
至少声明三项:background-color、color、padding;border-radius 是刚需,原生 <mark> 紧贴文字边缘太生硬。
- 深色模式必须显式适配:
@media (prefers-color-scheme: dark) { mark { background-color: #ffca28; color: #121212; } } - 别写
background: none——它不清除background-image,应写background-color: transparent - 色觉障碍用户可能无法识别黄底,靠
padding和border-radius提升视觉辨识度比换色更可靠 - 检查对比度是否 ≥4.5:1,用 Chrome DevTools 的 Accessibility 面板验证
用户选中文本后高亮,优先用 Range API 而非正则匹配
传统正则高亮(new RegExp(selectedText, 'g'))会全局匹配所有子串,导致“搜‘abc’却把‘ab’和‘bc’也染黄”,跨标签、跨换行、含空格的选区根本无法精准定位。
Range API 能拿到真实选区对象,用 document.getSelection().getRangeAt(0) 获取,再用 range.surroundContents(document.createElement('mark')) 原位包裹,完全绕过字符串解析风险。
- 注意
surroundContents()对空格和换行敏感,调用前先range.collapsed判断是否为有效选区 - 若需支持多次高亮并清除,记录每个
<mark>元素引用,避免用element.innerHTML = ...全量重写 - IE 不支持
surroundContents(),但 IE 已退出主流支持,无需 polyfill
真实项目里最容易被忽略的,是“高亮”这件事本身不该由样式决定——而是由语义驱动。你写的每一对 <mark>,都在告诉浏览器、读屏器、爬虫:“这段文字此刻与用户意图强相关”。一旦把它降级为视觉 hack,后续的可访问性、SEO、维护成本都会指数级上升。



















