在网页开发中,我们常常需要把某些标签里的文字从画面上藏起来,但又不能让使用屏幕阅读器的用户失去这些信息。比如一个只用图标表示的搜索按钮,可视用户靠图形就能理解,而视障用户仍需要“搜索”这两个字被读出来。如果处理不当,隐藏文本就会变成可访问性的漏洞。
为什么不能用display:none
不少初学者第一反应是用display:none把文字消掉,因为这样最简单。但按照无障碍规范,display:none会让元素彻底从渲染树和可访问性树里移除,屏幕阅读器根本不会碰到它。也就是说,视觉上藏住了,语义也跟着丢了。
下面这段代码虽然让按钮看起来只剩图标,但读屏软件会直接跳过,用户不知道这按钮是干什么的。
<button class="icon-only"> <span style="display:none;">搜索</span> <img src="search.png" alt="" /> </button>
除了可访问性问题,display:none还会让元素不占任何布局空间,如果后续用JavaScript切换显示状态,可能引发重排开销。在需要保留空间或动画过渡的场景里,它也不是好选择。
视觉隐藏但保留语义的常用方案
业界通常把这种“藏给眼睛看,留给读屏读”的做法叫视觉隐藏(visually hidden)。核心思路是:把元素移出可视区域或裁剪到不可见,但不使用display:none和visibility:hidden。最经典的是clip裁剪法。
下面的样式把一个类名为sr-only的元素限制在1像素内并裁掉溢出,同时用绝对定位脱离文档流,不影响周围布局。这种写法被Bootstrap等框架广泛采用。
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
使用方式非常简单,把需要隐藏的文本包一层即可:
<button class="icon-only"> <span class="sr-only">搜索</span> <img src="search.png" alt="" /> </button>
这种方案的优点是兼容性好、不破坏语义,缺点是要写一段较长的CSS。另外在极老版本IE里clip语法略有差异,不过现代项目基本不用考虑。
用text-indent负值的替代做法
另一种老派技巧是给标签设置超大负text-indent,把文字推到屏幕左边外面,再配合overflow:hidden截掉。它常用于替换文字的图片链接。
.hide-text {
text-indent: -9999px;
overflow: hidden;
white-space: nowrap;
}
这种方法在纯装饰性标题上曾经流行,但对读屏器不一定可靠,有些辅助技术会忽略被缩进的文本。而且负缩进可能产生横向滚动条,需要父级严控溢出。相比之下,clip方案更稳妥。
对比与选型建议
我们把三种方式放在一个表里看差异:
| 方式 | 视觉隐藏 | 读屏可读 | 布局影响 |
|---|---|---|---|
| display:none | 是 | 否 | 不占空间 |
| sr-only裁剪 | 是 | 是 | 脱离文档流 |
| text-indent负值 | 是 | 不一定 | 可能出滚动条 |
实际项目里,如果隐藏文本只为装饰或重复内容,用display:none没问题;若文本承载必要信息,请统一用视觉隐藏类。表单的label文字、图标按钮的说明都应走这条路线。
最后提醒,隐藏不等于乱藏。任何用sr-only包起来的字都该是真人能看懂的有用话,而不是堆给SEO的废话,否则就背离了可访问性初衷。