What's new in web accessibility
Media & Web 进阶 20m

Web 无障碍的新功能

What's new in web accessibility

2022年6月6日

在 Apple 官方观看视频

一句话判断

全球约七分之一的人有某种形式的残障——如果你的 Web 应用只考虑了鼠标和触摸交互,你正在排除大量潜在用户。这场 Session 教你如何构建真正可访问的自定义控件。

这场 Session 讲了什么

WebKit 无障碍团队的 Tyler 讲解了现代 Web 无障碍开发的核心技术。内容围绕三个主题:辅助技术概述、自定义控件的无障碍化、以及 Web Speech API 中的 SSML 支持。

Session 用一个在线测验应用作为示例,演示了如何将自定义披萨选择控件(点击添加/移除披萨片)改造为对 VoiceOver 用户完全可用的滑块控件。还展示了如何使用 SSML 控制 Safari 的语音合成输出。

核心信息是:语义 HTML 是首选方案,但当必须使用自定义 JavaScript 控件时,ARIA 属性和键盘事件处理是确保可访问性的关键。

值得深挖的点

自定义控件的无障碍化流程。 以披萨选择控件为例,无障碍化分四步:添加 role="slider" 赋予语义角色、添加 tabindex="0" 使其可聚焦、添加 aria-valuemin/aria-valuemax/aria-valuenow 描述值的范围和当前状态、添加 aria-valuetext 提供人类可读的描述。

Safari 的 VoiceOver 滑块手势映射。 在 iOS 上,VoiceOver 用户通过单指上下滑动来增减滑块值。Safari 自动将这些手势映射为箭头键事件——上滑映射为右箭头,下滑映射为左箭头。开发者只需要在 keydown 事件中处理箭头键,就能同时支持键盘和 VoiceOver 用户。

SSML 在 Web Speech API 中的支持。 Safari 现在支持在 SpeechSynthesis 中使用 SSML(语音合成标记语言)。你可以在文本中嵌入 <break> 标签插入停顿、使用 <say-as> 控制数字和日期的读法、使用 <prosody> 调整语速和音调。这让语音输出的体验更加自然。

视觉更新和 ARIA 更新必须同步。 一个重要的规则是:每次更新控件的视觉表示时,都必须同时更新 ARIA 属性。如果只更新了画面但没更新 aria-valuenowaria-valuetext,VoiceOver 用户看到的信息就会过期。

代码片段

<!-- 自定义滑块控件的 HTML 结构 -->
<div id="pizza-control"
     role="slider"
     tabindex="0"
     aria-valuemin="0"
     aria-valuemax="8"
     aria-valuenow="4"
     aria-valuetext="4片"
     aria-label="选择披萨片数">
  <!-- 自定义视觉渲染 -->
</div>
// 自定义控件的键盘事件处理
class PizzaControl {
    constructor(elementId) {
        this.element = document.getElementById(elementId);
        this.sliceCount = 4;
        
        // 点击事件处理
        this.element.addEventListener('click', (e) => {
            const newCount = this.calculateSliceFromClick(e);
            this.update(newCount);
        });
        
        // 键盘事件处理(同时支持键盘和 VoiceOver)
        this.element.addEventListener('keydown', (e) => {
            if (e.key === 'ArrowRight' || e.key === 'ArrowUp') {
                this.update(this.sliceCount + 1);
            } else if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') {
                this.update(this.sliceCount - 1);
            }
        });
    }
    
    update(newCount) {
        // 限制在有效范围内
        this.sliceCount = Math.max(0, Math.min(8, newCount));
        
        // 同步更新视觉和 ARIA 表示
        this.render();  // 更新画面
        this.element.setAttribute('aria-valuenow', this.sliceCount);
        const text = `${this.sliceCount}片`;
        this.element.setAttribute('aria-valuetext', text);
    }
}

// SSML 语音合成示例
const utterance = new SpeechSynthesisUtterance(
    `<speak>
        你选择了<break time="300ms"/>
        <say-as interpret-as="cardinal">4</say-as>片披萨。
    </speak>`
);
speechSynthesis.speak(utterance);

最佳实践

  • 优先使用语义 HTML 元素(button、h1-h6、table 等),它们自带无障碍支持
  • 自定义控件必须添加 role、tabindex 和适当的 ARIA 属性
  • 视觉更新和 ARIA 属性更新必须同步进行
  • 处理键盘事件时覆盖所有方向键(上下左右),确保 VoiceOver 手势和键盘导航都能工作
  • 利用 aria-valuetext 提供比数值更友好的描述
  • 使用 SSML 让语音合成输出更自然,添加适当的停顿和语调变化
  • 测试时用 VoiceOver 实际操作你的控件,而不仅仅看代码

还有什么值得关注

  • Apple 提供的辅助技术包括 VoiceOver、Switch Control、Voice Control 和 Full Keyboard Access
  • <dialog> 元素在 Safari 中获得更好的无障碍支持,推荐用于模态对话框
  • 配套观看 “Support Full Keyboard Access in your iOS app” 了解更多辅助技术细节
  • 全球约 14% 的人有某种形式的残障,无障碍不是小众需求
WWDC 2022