寻找失去的可访问性
Source: Woowahan Tech
您是否曾亲自检查过自己开发的服务的可访问性?在忙碌的日程中不断反映各种需求时,可访问性往往被视为“迟早要做的好事”。说实话,我们也曾这样想。
然而,如果忽视可访问性,实际使用过程中可能会出现超出预期的不便。例如,如果想购买商品需要在屏幕上点击上百次,那还能称之为正常的服务吗?
Tim Berners‑Lee(网页的创始人)曾这样说:
“网络的力量在于它的普遍性。让所有人都能访问,无论是否有障碍,这是最重要的部分。”
如果不能保持普遍性,我们的服务对某些人来说就等同于完全不可用的废物。
本文记录了在完成可访问性作业时,面对“几乎不可用的用户体验”并进行彻底改进的过程。网页可访问性的范围广阔且庞大,但本次工作聚焦于屏幕阅读器用户的体验。下面将介绍我们如何根据屏幕阅读器的实际朗读,改进商品详情页的可访问性。
什么是屏幕阅读器?
Android 的 TalkBack、iOS 的 VoiceOver 等辅助功能工具,用户可以通过左右滑动逐个浏览元素,并以语音方式朗读。
**参考:**本文中的屏幕阅读器朗读示例基于 iOS VoiceOver 编写。
为了到达“购买”按钮滑动了 300 多次
使用 Lighthouse 测得的商品详情页可访问性得分在 60~70 分之间,并不是很高,但仅通过在按钮上添加 aria-label、在图片上加入 alt 等常见做法,就能轻松拿到 90 分以上的分数。但实际情况真的改善了吗?
什么是 Lighthouse?
Lighthouse 是 Google 开发的网页质量自动化测评工具。它会检查性能(Performance)、可访问性(Accessibility)、SEO 等 5 大核心领域,并将结果换算为 0~100 分的分数。
现在我们闭着眼,只使用屏幕阅读器尝试购买商品。
咚!

在移动设备上使用屏幕阅读器进行测试的结果令人震惊。
- 虽然不同设备之间有细微差别,但要到达用户流程终点的 购买 按钮,需要进行 300 次以上的滑动操作。
- 即使在浏览过程中出现不感兴趣的内容,也必须滑动过去,这会导致相当大的疲劳感。
- 本应一次性朗读的文本被拆分了。例如 “990원” 被朗读为 “990” 和 “원”,这会导致额外的滑动并且难以把握上下文。
- 按钮的角色不明确。例如 “查看配送小费详情” 按钮仅被朗读为 “按钮”,用户无法知道它的功能。
问题归纳
- 疲劳的浏览:必须遍历所有元素,耗时长
- 碎片化的朗读:应一起朗读的文本被拆分,难以理解上下文
- 角色模糊:按钮未标明具体作用,用户无法判断其功能
总体来看,视觉浏览与屏幕阅读器浏览之间存在巨大差距。下面我们将踏上解决之旅。
重获可访问性的旅程
1. 创建浏览单元:地标(Landmark)和标题(Heading)
屏幕阅读器拥有强大的浏览功能。iOS VoiceOver 提供 Rotor,Android TalkBack 提供 单元浏览,可以快速在地标和标题之间跳转。
什么是地标?
地标标记页面的主要区域(页眉、主体、导航、页脚、章节等)。使用地标后,屏幕阅读器用户可以快速定位到想要的区域,充当“页面内地图”的角色。
我们的页面缺少合适的地标和标题结构,导致用户只能顺序浏览,就像没有目录的书只能从第一页逐行阅读一样。
为了解决这个问题,我们将页面划分为有意义的章节,并在每个章节放置明确的标题。

使用列表元素时的注意点
在 VoiceOver 中,若元素的 list-style: none 被设置,屏幕阅读器不会将其识别为列表。因此,如果通过 CSS 去掉了列表标记,需要显式声明 role="list"。
现在,屏幕阅读器用户可以通过标题或地标快速跳转到 “其他人一起看的商品”、 “优惠”等主要区域。

为了在整个页面统一使用这种结构,我们创建了可复用的组件。无需每次手动编写 section + heading + aria-labelledby,组件会自动处理。

2. 合并碎片化的文本
商品价格 “990원” 在屏幕阅读器中被朗读为 “990” 与 “원” 两段。除此之外,还有很多文本被拆分,导致需要额外的滑动才能完整阅读。

使用模板字面量
将数据以单一字符串形式输出,屏幕阅读器即可自然朗读。

如果因为样式需要拆分文本,可使用视觉上不可见的元素来补全朗读。

现在屏幕阅读器不再把文本拆开朗读,减少了不必要的滑动,内容也更易理解。
为什么不在 span 上使用 aria-label?
在 span 或 div 等普通容器上使用 aria-label,Android TalkBack 能正常工作,但 iOS VoiceOver 会忽略。aria-label 只在按钮、链接、地标、图片等交互元素上受支持。为在各种环境中提供一致体验,我们采用了 NoScreen 组件配合 aria-hidden 的方案。
3. 明确交互元素的角色
商品详情页中许多按钮仅被朗读为 “按钮”,或仅出现 “全部查看”“详细”,缺乏上下文。我们为它们添加了说明,明确 查看什么、详细展示什么。

切换按钮 也存在问题。屏幕阅读器无法获知收藏按钮的当前状态。我们使用 aria-pressed 来传递切换状态。

打开模态框或底部弹窗的按钮同样缺乏提示,用户无法预判点击后会发生什么。我们使用 aria-haspopup 与 aria-expanded 来标识状态。

最终,用户仅凭屏幕阅读器的朗读就能了解按钮的功能和行为。
再次找回的可访问性
改进后最显著的变化是 浏览次数。到达购买按钮所需的滑动次数降至 20 次以下,提升幅度超过 90%。文本朗读和交互元素的优化,使得屏幕阅读器的浏览体验与视觉浏览的体验更加接近。
为开发者准备的可访问性指南
可访问性改进最初是为屏幕阅读器用户而做,但在实践过程中也给开发者带来了诸多好处。
-
使用 语义化标签 后,仅凭代码结构就能快速了解页面布局。标签名称本身就定义了元素的角色和意义。

-
可以 以真实用户的浏览流程 来编写测试。过去的
className、data-testid等选择器与用户体验相距甚远,改为基于role的选择后,测试代码更具意义。

结语
可访问性改进,会让人觉得很难吗?
我们起初也觉得这是一件模糊且困难的事。但真正动手后发现并没有想象中那么难,还学到了很多以前不懂的知识。
最让我们印象深刻的是 不要盲目相信 Lighthouse 分数。即使分数很高,实际使用屏幕阅读器浏览时仍可能非常困难。亲自进行数百次滑动的体验,让我们深刻感受到问题的严重性。
我们把这次的收获整理成了指南:
- 语义化标签使用指南
- ARIA 属性应用模式
- 代码评审时的可访问性检查清单
- 可复用的可访问性组件示例
寻找可访问性的旅程并未结束。我们计划将这套改进方法推广到其他页面,并考虑实现自动化的可访问性测试,以提升开发效率。同时,也在为 AI 编写可访问性规则,让新组件从一开始就具备可访问性。
阅读本文的您,不妨抽空打开手机的屏幕阅读器,感受一下熟悉界面在语音下的表现。您会发现许多问题,也会迈出为所有人打造更好网络的第一步。
希望我们的经验能为您的可访问性改进之路提供一点帮助。