aria-hidden="true”仅对辅助技术隐藏纯装饰性元素(如空图标、分隔线、背景花纹),不影响视觉显示;禁用于任何可交互或可聚焦元素,不可替代display:none或visibility:hidden。

aria-hidden="true" 是唯一能“视觉留着、读屏跳过”的方式,不是隐藏指令,而是语义剔除开关。
哪些元素该加 aria-hidden="true
只用于纯装饰、无功能语义的节点:
- 空图标:
<svg aria-hidden="true"><use href="#icon-close"></use></svg>(旁边已有“关闭”文字) - 分隔线:
<hr aria-hidden="true">(仅作视觉分割,无结构意义) - 背景花纹容器:
<div class="deco-pattern" aria-hidden="true"></div> - 轮播指示器容器(若已有语音提示或标题)
⚠️ 绝对不要加在:<button></button>、<a></a>、带 tabindex="0" 的 <div>、或任何可能被键盘聚焦的元素上。
<h3>为什么不能用 <code>display: none 或 visibility: hidden 替代
它们会同时移除视觉呈现和辅助技术可访问性,而 aria-hidden="true" 只动语义树:
-
display: none→ 元素从渲染树和辅助功能树中彻底消失,JS 也查不到(getBoundingClientRect()返回空) -
visibility: hidden→ 占布局、不可见、不被读取,但事件仍可触发(容易误点) -
aria-hidden="true"→ 元素照常显示、可点击、可获取尺寸、DOM 存在,仅屏幕阅读器跳过
混用是常见错误:给 display: none 的元素再加 aria-hidden="true" 是冗余;只加 aria-hidden="true" 却没做视觉隐藏,会导致“看到空白却听不到解释”。
嵌套时最易踩的坑
父元素设了 aria-hidden="true",所有子元素(包括按钮、链接)都会被跳过,且子元素显式写 aria-hidden="false" 在多数浏览器中无效:
- ❌ 错误:
<div aria-hidden="true"><button aria-hidden="false">确定</button></div>→ 屏幕阅读器完全读不到“确定” - ✅ 正确:把
aria-hidden加在纯装饰容器上,交互控件必须在它之外 - ⚠️ SVG 内部的
<title></title>或<desc></desc>仍可能被读出,需一并加aria-hidden="true"或直接删掉 - 动态显示模态框时,别只切 CSS 类;背景遮罩层要手动加
aria-hidden="true",模态内容区要同步移除
比 aria-hidden 更安全的替代写法
真正需要精细控制语义暴露的场景其实不多,优先考虑更底层的语义化方案:
- CSS 伪元素渲染图标:
::before { content: "★"; }→ 完全脱离 DOM,零 ARIA 开销 - 内联 SVG 加
role="presentation"+focusable="false"(防 Safari/Firefox 键盘聚焦 SVG) - 用
<img src="star.svg" alt="">,空alt已天然表达“装饰性”
动态切换时,焦点管理永远比 aria-hidden 状态更重要——状态变了,但焦点卡在旧元素上,用户就断连了。











