富文本输出的HTML破坏可访问性源于编辑器默认不关心可访问性,导致语义缺失、结构错误及样式污染;必须显式声明lang、保留语义标签、清洗时兼顾AT需求,并隔离展示层样式。

为什么富文本输出的 HTML 会破坏可访问性
不是编辑器“没做对”,而是它压根不关心可访问性。Quill、TinyMCE、CKEditor 默认生成的 HTML 常见问题包括:<p> 嵌套 <div>、空 <p></p>、缺失 lang 属性、<img> 没 alt、链接无 title 或 aria-label、列表项用 <div> 模拟而非 <ul>/<ol>。这些在视觉上可能“看起来一样”,但屏幕阅读器会跳过、误读或完全忽略内容。
必须补上的三个基础结构标签
<html>、<head>、<body> 不能靠浏览器自动补全——尤其 SSR 或微前端场景下,缺一不可:
-
<html lang="zh-CN">必须显式声明,否则 JAWS/NVDA 会按系统默认语言朗读中文,发音严重错乱 -
<title>不可为空、不可用占位符(如 “Untitled”),它是屏幕阅读器进入页面后第一个播报的内容 -
<meta name="viewport">缺失会导致移动端 AT(辅助技术)无法正确缩放和定位,iOS VoiceOver 可能直接跳过整个区域
清洗时别只盯着 XSS,更要保留语义标签
DOMPurify 默认白名单太激进,会干掉 <figure>、<figcaption>、<aside> 等语义化标签。清洗策略得改:
- 白名单中明确加入
figure、figcaption、aside、main、section、header、nav - 允许
<img>的alt和loading属性(loading="lazy"对 AT 友好且不影响性能) - 对
<a>至少保留href+title或aria-label,禁止删空链接但允许带说明 - 空
<p></p>不能简单删除——需转为<p aria-hidden="true"> </p>,否则段落间距塌陷,AT 仍能感知空白段落存在
展示层必须隔离样式,否则可访问性前功尽弃
编辑器输出的内联 style 或类名(如 class="mce-item-table")会污染全局样式,更致命的是覆盖用户代理样式(user agent stylesheet),导致高对比度模式失效:
立即学习“前端免费学习笔记(深入)”;
- 禁止在展示容器上直接用
v-html或innerHTML渲染原始 HTML - 必须包裹在独立
<article class="rich-content">容器中,并用 CSS 隔离:.rich-content * { all: unset; }+ 显式重置关键属性(font-size、line-height、color) - 对
<table>强制加role="table"、<th>加scope="col"/scope="row",否则表格无法被 AT 导航 - 所有自定义图标用
<svg>+<title>或aria-hidden="true"+ 文本替代,禁用仅靠 class 控制的 icon font
可访问性不是加个 aria-label 就完事,而是从 DOM 结构、语义标签、样式隔离到 AT 行为响应的完整链路。最容易被跳过的环节,是清洗后没做展示层样式重置——哪怕结构全对,一挂全局 CSS,高对比度模式就立即失效。



















