最稳妥的视觉隐藏方案是使用 w3c 推荐的 css 组合:position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0。

用 visibility: hidden 或 display: none 都不行——它们会让屏幕阅读器跳过元素,破坏可访问性。
怎么让元素“看不见但读得着”
核心是视觉隐藏 + 语义保留:元素仍在 DOM 中、有语义、能被屏幕阅读器识别,但对 sighted 用户不可见。最稳妥的方式是组合 CSS 属性,绕过浏览器对 display: none 和 visibility: hidden 的可访问性屏蔽。
-
position: absolute+clip: rect(0 0 0 0)(旧写法)或clip-path: inset(50%)(现代推荐) - 必须保留
width和height为非零值(否则部分读屏器会忽略) - 避免用
opacity: 0单独使用——它仍占布局、可聚焦、可能被误操作 - 不要加
aria-hidden="true",否则直接切断读屏通路
为什么不用 sr-only 类就容易翻车
很多项目直接复制网上流传的 .sr-only 片段,但没注意浏览器版本和读屏器差异。比如老版 IE 不支持 clip-path,而某些 NVDA 版本对 border: 0 + padding: 0 组合敏感。
- 推荐用 W3C 官方认可的最小安全集合:
position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; - 如果用
clip-path: inset(50%),需加@supports (clip-path: inset(0))回退 - 绝对定位本身不破坏语义,但若父容器是
overflow: hidden,可能把隐藏内容裁掉——这时要检查层级和容器样式
aria-label 和视觉隐藏文本该选哪个
不是二选一,是场景决定。两者解决的问题不同:一个是“替换”可访问名称,一个是“补充”上下文。
立即学习“前端免费学习笔记(深入)”;
- 按钮图标没文字?优先用
aria-label,简单直接:<button aria-label="关闭"></button> - 需要提供额外说明(如“仅限会员”“已过期”),且该信息对 sighted 用户也应存在(只是换种方式呈现),就用视觉隐藏文本:
<span class="visually-hidden">仅限会员</span> - 混用风险:同时写
aria-label和视觉隐藏子元素,会导致读屏器重复播报——aria-label会覆盖所有子内容 - 表单
label里嵌视觉隐藏文本是安全的,因为label本身是可访问容器
真正难的不是写对那几行 CSS,而是每次加隐藏文本时,都得想清楚:这个信息对谁有用?是否所有用户路径(键盘、触控、读屏)都能一致抵达?漏掉任一路径,就等于没藏好——只是换种方式暴露了缺陷。











