accessibility

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Accessibility

无障碍

Web accessibility done right means your UI is navigable, understandable, and operable by people who cannot use a mouse — primarily those using screen readers (NVDA, JAWS, VoiceOver), keyboard-only users, and those with motor, cognitive, or visual impairments. The 2024 WebAIM Million report found 95.9% of home pages failing basic accessibility checks. Most failures are preventable with the right mental model.
正确实现Web无障碍意味着你的UI可以被无法使用鼠标的用户导航、理解和操作——主要是使用屏幕阅读器(NVDA、JAWS、VoiceOver)的用户、仅使用键盘的用户,以及有运动、认知或视觉障碍的用户。2024年WebAIM百万网站报告显示,95.9%的首页未通过基础无障碍检查,大多数问题只要采用正确的思维模型就能避免。

The Core Mental Model

核心思维模型

Screen readers linearise a 2D page into a 1D audio stream. A blind user never sees the whole page at once — they navigate sequentially by headings, landmarks, form fields, links, and interactive controls using keyboard shortcuts. Every decision you make should answer: "What will a screen reader announce, and does it make sense in isolation?"
The three rules that flow from this:
  1. Semantics over style — use native HTML elements (
    <button>
    ,
    <nav>
    ,
    <h2>
    ) before reaching for ARIA. Native elements come with free keyboard support, accessible names, and correct roles.
  2. Context must travel with the element — a screen reader user navigating by tab or by links list sees elements stripped of their visual neighbours. Labels, descriptions, and states must be programmatically attached, not implied by proximity.
  3. Dynamic changes must be announced — screen readers only notice changes if focus moves to new content or a live region announces it. Silent DOM mutations are invisible to AT.

屏幕阅读器会将2D页面线性化为1D音频流。失明用户无法同时看到整个页面——他们通过键盘快捷键按标题地标表单字段链接交互控件顺序导航。你做的每一个决策都要回答:"屏幕阅读器会播报什么内容,脱离上下文它是否合理?"
由此衍生出三条核心规则:
  1. 语义优先于样式——在使用ARIA之前优先使用原生HTML元素(
    <button>
    <nav>
    <h2>
    )。原生元素自带开箱即用的键盘支持、无障碍名称和正确的角色。
  2. 上下文必须随元素传递——通过Tab键或链接列表导航的屏幕阅读器用户看到的元素是脱离周边视觉内容的。标签、描述和状态必须以编程方式绑定,而非通过视觉位置暗示。
  3. 动态变化必须被播报——只有当焦点移动到新内容或实时区域播报变化时,屏幕阅读器才会感知到变化。无提示的DOM变更对辅助技术(AT)不可见。

When Auditing Existing UI

审计现有UI时的优先级

Review in this priority order — fix critical issues before polishing low-impact ones:
PriorityCategoryWCAG LevelSee
1Accessible names (buttons, inputs, links)Areferences/aria-patterns.md
2Keyboard operability (all interactive elements)Areferences/focus-management.md
3Focus management (dialogs, SPAs, live regions)A/AAreferences/focus-management.md
4Semantic structure (headings, landmarks, lists)Areferences/wcag-checklist.md
5Form errors and validationA/AAreferences/common-fixes.md
6Colour contrast and visual statesAAreferences/wcag-checklist.md
7Dynamic content announcementsAAreferences/aria-patterns.md
8Images and mediaAreferences/wcag-checklist.md
Quote the exact failing snippet, name the WCAG criterion, and propose the smallest viable fix. Do not refactor unrelated code.

按以下优先级顺序审核——先修复严重问题,再优化低影响问题:
优先级分类WCAG等级参考文档
1无障碍名称(按钮、输入框、链接)Areferences/aria-patterns.md
2键盘可操作性(所有交互元素)Areferences/focus-management.md
3焦点管理(对话框、单页应用、实时区域)A/AAreferences/focus-management.md
4语义结构(标题、地标、列表)Areferences/wcag-checklist.md
5表单错误与校验A/AAreferences/common-fixes.md
6颜色对比度与视觉状态AAreferences/wcag-checklist.md
7动态内容播报AAreferences/aria-patterns.md
8图片与媒体Areferences/wcag-checklist.md
需引用具体的问题代码片段,标注对应的WCAG准则,并提出最小可行修复方案,不要重构不相关的代码。

When Building New UI

构建新UI时的规范

The quick decision tree

快速决策树

Need an interactive control?
Does a native HTML element do this?  → YES → Use it. Done.
  ↓ NO
Use the correct ARIA role + required attributes + keyboard handler.

Adding dynamic content?
Does focus move to the new content? → YES → No live region needed.
  ↓ NO
Is it a transient status (toast, cart count, form error)?
  → Use aria-live="polite" (or role="alert" for errors)

Opening a dialog/modal?
  → Trap focus inside. Restore focus to trigger on close.
  → See references/focus-management.md
需要交互控件?
原生HTML元素是否满足需求?  → 是 → 直接使用,完成。
  ↓ 否
使用正确的ARIA角色 + 必要属性 + 键盘事件处理。

添加动态内容?
焦点是否会移动到新内容? → 是 → 不需要实时区域。
  ↓ 否
是否是临时状态提示(toast、购物车计数、表单错误)?
  → 使用aria-live="polite"(错误提示使用role="alert")

打开对话框/模态框?
  → 把焦点限制在对话框内部,关闭时将焦点恢复到触发元素。
  → 参考 references/focus-management.md

Mandatory checks before shipping any interactive component

交付任何交互组件前的强制检查项

  • Every input, select, textarea has an associated
    <label>
    (not just placeholder)
  • Every button has an accessible name (text content,
    aria-label
    , or
    aria-labelledby
    )
  • Every icon-only control has
    aria-label
    ; the icon has
    aria-hidden="true"
  • Focus is visible on all interactive elements (never
    outline: none
    without a replacement)
  • Tab order is logical and matches visual order
  • All pointer interactions have a keyboard equivalent
  • No
    tabindex
    greater than 0

  • 所有input、select、textarea都有对应的
    <label>
    (不只有占位符)
  • 所有按钮都有可访问名称(文本内容、
    aria-label
    aria-labelledby
  • 所有纯图标控件有
    aria-label
    ;图标本身设置
    aria-hidden="true"
  • 所有交互元素的焦点状态可见(永远不要只写
    outline: none
    而不提供替代样式)
  • Tab顺序逻辑清晰,和视觉顺序一致
  • 所有指针交互都有对应的键盘操作等价方案
  • 没有大于0的
    tabindex

The Five Most Common Failures (and their fixes)

五大最常见问题(及修复方案)

1. Icon-only button with no accessible name

1. 纯图标按钮没有可访问名称

html
<!-- ❌ Screen reader announces: "button" -->
<button><svg>...</svg></button>

<!-- ✅ Screen reader announces: "Close, button" -->
<button aria-label="Close"><svg aria-hidden="true">...</svg></button>
html
<!-- ❌ 屏幕阅读器播报:"button" -->
<button><svg>...</svg></button>

<!-- ✅ 屏幕阅读器播报:"Close, button" -->
<button aria-label="Close"><svg aria-hidden="true">...</svg></button>

2. Input with no label

2. 输入框没有标签

html
<!-- ❌ Screen reader announces: "edit text" -->
<input type="email" placeholder="Email" />

<!-- ✅ Screen reader announces: "Email address, edit text" -->
<label for="email">Email address</label>
<input id="email" type="email" />
html
<!-- ❌ 屏幕阅读器播报:"edit text" -->
<input type="email" placeholder="Email" />

<!-- ✅ 屏幕阅读器播报:"Email address, edit text" -->
<label for="email">Email address</label>
<input id="email" type="email" />

3. div or span used as a button

3. 使用div或span作为按钮

html
<!-- ❌ Not keyboard accessible, no role announced -->
<div onclick="save()">Save</div>

<!-- ✅ Free keyboard support, correct role -->
<button onclick="save()">Save</button>
html
<!-- ❌ 不支持键盘访问,没有角色播报 -->
<div onclick="save()">Save</div>

<!-- ✅ 原生支持键盘操作,角色正确 -->
<button onclick="save()">Save</button>

4. Form error not linked to field

4. 表单错误未和字段关联

html
<!-- ❌ Error visible but not associated with the field -->
<input id="email" type="email" />
<span>Please enter a valid email</span>

<!-- ✅ Screen reader announces error when field is focused -->
<input id="email" type="email"
       aria-describedby="email-err"
       aria-invalid="true" />
<span id="email-err" role="alert">Please enter a valid email</span>
html
<!-- ❌ 错误可见但未和输入框关联 -->
<input id="email" type="email" />
<span>Please enter a valid email</span>

<!-- ✅ 输入框获得焦点时屏幕阅读器会播报错误 -->
<input id="email" type="email"
       aria-describedby="email-err"
       aria-invalid="true" />
<span id="email-err" role="alert">Please enter a valid email</span>

5. Dynamic content updated silently

5. 动态内容静默更新

html
<!-- ❌ Cart count updates, screen reader users never know -->
<span id="cart-count">3</span>

<!-- ✅ Announces "4 items in cart" when count changes -->
<span id="cart-count" aria-live="polite" aria-atomic="true">4 items in cart</span>

html
<!-- ❌ 购物车计数更新,但屏幕阅读器用户完全感知不到 -->
<span id="cart-count">3</span>

<!-- ✅ 计数变化时播报 "4 items in cart" -->
<span id="cart-count" aria-live="polite" aria-atomic="true">4 items in cart</span>

Screen Reader Testing

屏幕阅读器测试

Automated tools catch ~30–40% of accessibility issues. The rest require AT testing.
Minimum viable test matrix:
  • NVDA + Chrome or Firefox (Windows) — covers ~66% of screen reader users
  • VoiceOver + Safari (macOS/iOS) — covers Apple ecosystem
  • Add JAWS + Chrome for enterprise contexts
Core navigation patterns to test manually:
  1. Tab through all interactive elements — are names and roles announced correctly?
  2. Press
    H
    to navigate by headings — is the page structure logical?
  3. Press
    D
    to navigate by landmarks — are regions clearly labelled?
  4. Open and close any dialogs — does focus trap, then restore?
  5. Submit a form with errors — are error messages announced?
  6. Trigger any dynamic content update — is the change announced?
See references/screen-readers.md for NVDA/JAWS/VoiceOver commands, browse vs. forms mode, and testing scripts.

自动化工具只能检测到约30-40%的无障碍问题,剩余问题需要通过辅助技术测试发现。
最低测试矩阵要求:
  • NVDA + Chrome 或 Firefox(Windows)——覆盖约66%的屏幕阅读器用户
  • VoiceOver + Safari(macOS/iOS)——覆盖苹果生态用户
  • 企业级场景额外添加 JAWS + Chrome 测试
需要手动测试的核心导航场景:
  1. 按Tab键遍历所有交互元素——名称和角色是否播报正确?
  2. H
    键按标题导航——页面结构是否逻辑通顺?
  3. D
    键按地标导航——区域是否标注清晰?
  4. 打开和关闭所有对话框——焦点是否被限制在内部,关闭后是否恢复到触发元素?
  5. 提交有错误的表单——错误信息是否被播报?
  6. 触发所有动态内容更新——变化是否被播报?
查看 references/screen-readers.md 了解NVDA/JAWS/VoiceOver命令、浏览模式与表单模式的区别,以及各组件类型的测试脚本。

ARIA: The Rules

ARIA使用规则

Rule 0: Don't use ARIA if native HTML solves it. Bad ARIA is worse than no ARIA.
Rule 1:
aria-label
and
aria-labelledby
provide the accessible name (what the element is). Rule 2:
aria-describedby
provides supplementary description (what it does or needs). Rule 3:
aria-live="polite"
for non-urgent updates;
role="alert"
(implicit
assertive
) for errors. Rule 4: Live regions must exist in the DOM on page load — inject text into them, don't inject the region itself. Rule 5:
aria-hidden="true"
removes from the AT tree completely. Never apply to focusable elements.
Full ARIA pattern library → references/aria-patterns.md

规则0: 如果原生HTML可以解决问题就不要用ARIA,错误的ARIA比没有ARIA更糟糕。
规则1:
aria-label
aria-labelledby
提供可访问名称(说明元素是什么)。 规则2:
aria-describedby
提供补充描述(说明元素的作用或要求)。 规则3: 非紧急更新使用
aria-live="polite"
;错误提示使用
role="alert"
(隐式包含assertive优先级)。 规则4: 实时区域必须在页面加载时就存在于DOM中——只能向区域内注入文本,不要动态注入区域本身。 规则5:
aria-hidden="true"
会将元素完全从辅助技术树中移除,永远不要应用在可聚焦元素上。
完整ARIA模式库见 references/aria-patterns.md

Visually Hidden Content

视觉隐藏内容

To show content to screen readers but hide it visually:
css
.visually-hidden:not(:focus):not(:active) {
  clip-path: inset(50%);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}
Use for: skip links, supplementary link context ("Read more <span class="visually-hidden">about caching</span>"), icon button labels when
aria-label
is impractical for translation reasons.
Do not use for: content that sighted users need. Hiding meaningful content from one group creates disparity, not accessibility.

如果需要让屏幕阅读器识别内容但对视觉用户隐藏,可以使用以下CSS:
css
.visually-hidden:not(:focus):not(:active) {
  clip-path: inset(50%);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}
适用场景:跳转链接、补充链接上下文("阅读更多 <span class="visually-hidden">关于缓存的内容</span>")、因翻译问题不适合用
aria-label
的图标按钮标签。
禁止用于:视觉用户需要看到的内容。对某一类用户隐藏有意义的内容只会造成差异,而非实现无障碍。

Colour and Contrast (WCAG AA)

颜色与对比度(WCAG AA标准)

Content typeMinimum ratio
Body text (<18pt / <14pt bold)4.5:1
Large text (≥18pt or ≥14pt bold)3:1
UI components (borders, icons, focus rings)3:1
Placeholder text4.5:1
Disabled elementsExempt
Never convey information by colour alone — always pair with a shape, pattern, or text label.

内容类型最小对比度
正文文本(<18pt / <14pt 粗体)4.5:1
大文本(≥18pt 或 ≥14pt 粗体)3:1
UI组件(边框、图标、焦点环)3:1
占位符文本4.5:1
禁用状态元素无要求
永远不要仅通过颜色传递信息——必须同时搭配形状、图案或文本标签。

Reference Files

参考文件

FileContents
references/screen-readers.mdNVDA/JAWS/VoiceOver commands, browse vs. forms mode, testing scripts per component type
references/aria-patterns.mdARIA roles, labelling hierarchy, live region patterns, complex widget ARIA (combobox, tabs, tree)
references/focus-management.mdModal focus trap, SPA route change focus, skip links, focus restoration patterns
references/wcag-checklist.mdWCAG 2.2 AA criterion-by-criterion checklist with pass/fail examples
references/common-fixes.mdCode-level fix templates for the 20 most common audit findings
文件内容
references/screen-readers.mdNVDA/JAWS/VoiceOver命令、浏览模式与表单模式说明、各组件类型测试脚本
references/aria-patterns.mdARIA角色、标签优先级、实时区域模式、复杂组件ARIA(下拉框、标签页、树形结构)
references/focus-management.md模态框焦点捕获、单页应用路由切换焦点管理、跳转链接、焦点恢复模式
references/wcag-checklist.mdWCAG 2.2 AA逐准则检查清单,包含通过/失败示例
references/common-fixes.md20种最常见审计问题的代码级修复模板