是唯一传达“上下文相关临时高亮”语义的html元素,必须用于搜索结果、引用锚点等承载上下文信息的场景;固定ui高亮应使用;需显式设置background-color、color、padding、border-radius及暗色模式适配;动态高亮须用treewalker+range避免dom破坏与xss。

mark 标签不是“加个黄底”的快捷方式,它是唯一能向浏览器、屏幕阅读器和搜索引擎明确传达「这段文本因当前上下文(比如搜索、引用、审阅)被临时标出」的语义化元素。
什么时候必须用 mark,而不是 span + class?
核心判断只有一条:高亮是否承载「上下文相关性」这个信息。
- 用户搜
"React",结果页中所有出现的React都该用<mark>React</mark>——读屏软件会读作「高亮文本 React」,搜索引擎可能单独索引这些片段 - 文档里写「参见
<mark>第 3.2 节</mark> 的说明」,表示这是当前段落指向的锚点,不是永久强调
- 代码编辑器里实时匹配用户输入的变量名(如
userInput),用 <code>mark表明「此处命中了你正在找的内容」 - 反过来,按钮上写「
<span class="highlight">限时抢购</span>」更合适——这是固定 UI 文案,无上下文依赖,加mark反而会让辅助技术误判为「搜索结果」
mark 默认样式不可靠,必须显式声明哪些 CSS 属性?
浏览器 UA 样式只在部分环境下生效,禁用样式、邮件客户端、阅读模式、Windows 高对比度模式下,mark 可能完全隐形或文字糊成一团。
- 必须设置
background-color和color,不能留空或依赖继承 - 必须加
padding(推荐0.1em 0.3em),否则背景紧贴文字,边缘生硬且可读性差 - 建议加
border-radius: 3px和轻微box-shadow: inset 0 -2px 0 rgba(0,0,0,0.1),提升视觉区分度 - 暗色模式下务必用
@media (prefers-color-scheme: dark)单独定义,比如把黄色换成#ffca28,文字色调深
用 JavaScript 动态高亮关键词,为什么不能直接 innerHTML.replace()?
这种写法看似简单,实际会破坏 DOM 结构、引入 XSS 风险、导致事件丢失,并在嵌套标签中彻底失效。
- 原始文本是
<strong>React</strong> Native,正则替换后可能变成<mark><strong>React</strong></mark> Native,mark包裹了整个strong元素,语义错乱 - 用户输入
<script>alert(1)</script>作为关键词,拼进innerHTML就直接执行脚本 - 表单输入框的值、绑定的事件监听器、动态插入的子节点,全部会在
replace()后消失 - 正确做法是用
TreeWalker遍历NodeFilter.SHOW_TEXT,对纯文本节点做matchAll(),再用Range.surroundContents()或node.splitText()精准包裹
中文搜索高亮容易踩的边界坑
中文没有空格分隔,new RegExp(keyword, 'gi') 会导致「服务」匹配到「服务器」「微服务」里,高亮错位。
- 不要用
\b(它对中文无效),改用 Unicode 边界断言:/(? -
escapedKeyword必须先对正则特殊字符(如.、[、?)做转义,否则user.name会变成匹配任意字符 - 多词搜索时,用
input.trim().split(/\s+/).filter(Boolean)拆词,再按长度降序排序,避免短词在长词内部重复匹配 - 高亮后若出现换行错位、背景撑开,检查父容器是否设了
white-space: pre-line或display: flex,给mark加display: inline; vertical-align: baseline;强制重置盒模型
真正难的从来不是怎么写那行 <mark>xxx</mark>,而是每次动笔前,得想清楚:这段高亮,是给人看的,还是给机器读的,还是两者都得兼顾——漏掉任何一端,mark 就只是个带颜色的 span。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











