应使用 clip-path: inset(50%) 或 clip: rect(1px, 1px, 1px, 1px) 实现视觉隐藏但保留可访问性,二者仅影响绘制不干扰语义;禁用 visibility: hidden、opacity: 0 和 display: none,因其会强制屏幕阅读器跳过内容。

用 clip-path 或 clip 实现视觉隐藏但保留可访问性
直接设 visibility: hidden 或 display: none 都会让屏幕阅读器跳过内容,这不是“隐藏给眼睛看”,而是“彻底藏起来”。真正要让元素对视觉用户不可见、却仍被读屏软件识别,得用裁剪类方案:clip-path: inset(50%)(现代推荐)或老式 clip: rect(0, 0, 0, 0)(仅支持绝对定位元素)。
关键点在于:这些属性只影响绘制阶段,不改变 DOM 结构、不干扰语义、不阻断可访问性树遍历。
-
clip-path: inset(50%)更安全——它不强制position: absolute,也不依赖旧版rect()语法 - 若需兼容 IE,只能退回到
clip: rect(1px, 1px, 1px, 1px)+position: absolute组合(注意不能写rect(0,0,0,0),某些浏览器会失效) - 避免用
opacity: 0或visibility: hidden,它们虽保布局,但多数读屏器默认忽略
为什么 visibility: hidden 不行?
它确实保留占位、不触发重排,但规范明确要求屏幕阅读器跳过 visibility: hidden 元素——这不是浏览器 bug,是 WAI-ARIA 的设计意图。即使你没加 aria-hidden="true",它也默认不可访问。
常见误判场景:
- 表单里用
visibility: hidden隐藏错误提示,键盘用户 Tab 到<input>时,读屏器不会播报错误信息 - 图标旁的辅助文本(如“搜索按钮”)被设为
visibility: hidden,视障用户根本不知道按钮功能 -
getComputedStyle(el).visibility === 'hidden'返回true,但el.ariaHidden是null,不代表可访问
用 aria-hidden="false" 能补救吗?
不能。aria-hidden="false" 是无效值,WAI-ARIA 规范只接受 true 或 false 字符串,但 false 并不表示“启用可访问性”,它只是撤销显式隐藏声明,不覆盖原生语义规则。而 visibility: hidden 的可访问性屏蔽是强制的,aria-hidden 无法翻转。
真正有效的组合只有两种:
- 视觉隐藏 + 可访问:用
clip-path或clip,不设任何aria-hidden - 彻底移除 + 可访问控制:用
display: none+aria-hidden="true"(此时已无需读屏器读取)
实际写法与容易漏掉的细节
最稳妥的现代写法是:
.visually-hidden {
position: absolute;
clip-path: inset(50%);
/* 备用:针对不支持 clip-path 的旧环境 */
clip: rect(1px, 1px, 1px, 1px);
padding: 0 !important;
border: 0 !important;
height: 1px !important;
width: 1px !important;
overflow: hidden;
}
必须加 position: absolute 是因为 clip-path: inset() 在非定位元素上行为不稳定;!important 是为了压制组件库可能注入的样式冲突;overflow: hidden 防止某些浏览器意外溢出。
最容易被忽略的是:这类类名一旦定义,就该全局复用,而不是每个项目手写一遍——稍有差异(比如漏了 position 或用了 inset(100%)),可访问性就断了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











