⚠️ Alpha内测版本警告:此为早期内部构建版本,尚不完整且可能存在错误,欢迎大家提Issue反馈问题或建议
Skip to content

3.8.1 WCAG 标准

一句话破题

WCAG 是可访问性的"交规",遵守它,你的网站就能让更多人使用。

核心价值

WCAG (Web Content Accessibility Guidelines) 是 W3C 制定的可访问性标准。满足 WCAG 2.1 AA 级是大多数法规要求的最低标准。

WCAG 四大原则

原则含义关键要求
可感知用户能感知到内容图片有替代文本、视频有字幕
可操作用户能操作界面键盘可访问、有足够时间
可理解用户能理解内容语言清晰、行为可预测
健壮性兼容辅助技术语义化 HTML、ARIA 属性

键盘可访问性

核心要求:所有功能必须能通过键盘操作。

tsx
// 差:div 做按钮,无法键盘访问
<div onClick={handleClick}>点击我</div>

// 好:使用原生 button
<button onClick={handleClick}>点击我</button>

// 如果必须用 div,添加必要属性
<div 
  role="button"
  tabIndex={0}
  onClick={handleClick}
  onKeyDown={(e) => {
    if (e.key === 'Enter' || e.key === ' ') {
      handleClick()
    }
  }}
>
  点击我
</div>

焦点管理

tsx
// 焦点可见
.focus-visible:focus {
  outline: 2px solid #2563eb;
  outline-offset: 2px;
}

// 跳过导航链接
<a href="#main" className="sr-only focus:not-sr-only">
  跳转到主要内容
</a>

<main id="main">...</main>

语义化 HTML

tsx
// 差:div 嵌套一切
<div class="nav">
  <div class="nav-item">首页</div>
</div>
<div class="main">
  <div class="title">文章标题</div>
</div>

// 好:语义化标签
<nav>
  <a href="/">首页</a>
</nav>
<main>
  <h1>文章标题</h1>
  <article>...</article>
</main>

ARIA 属性

当语义化 HTML 不够时,使用 ARIA:

tsx
// 模态框
<div
  role="dialog"
  aria-labelledby="dialog-title"
  aria-describedby="dialog-description"
  aria-modal="true"
>
  <h2 id="dialog-title">确认删除</h2>
  <p id="dialog-description">删除后无法恢复,确定吗?</p>
  <button>确定</button>
  <button>取消</button>
</div>

// 加载状态
<button aria-busy={isLoading} disabled={isLoading}>
  {isLoading ? '保存中...' : '保存'}
</button>

// 展开/收起
<button 
  aria-expanded={isOpen}
  aria-controls="menu-content"
>
  菜单
</button>
<div id="menu-content" hidden={!isOpen}>
  ...
</div>

常用 ARIA 属性

属性用途示例
aria-label为元素提供标签<button aria-label="关闭">X</button>
aria-labelledby引用另一元素作为标签aria-labelledby="title"
aria-describedby引用描述性文本aria-describedby="help-text"
aria-hidden对辅助技术隐藏<div aria-hidden="true">装饰性内容</div>
aria-live动态内容区域<div aria-live="polite">
role定义元素角色role="button"

图片替代文本

tsx
// 信息性图片:描述内容
<img 
  src="/chart.png" 
  alt="2024年销售额增长趋势图,Q1到Q4分别为100万、150万、200万、280万"
/>

// 装饰性图片:空 alt
<img src="/decorative-line.png" alt="" />

// 功能性图片:描述功能
<button>
  <img src="/search-icon.svg" alt="搜索" />
</button>

表单可访问性

tsx
// 关联 label 和 input
<div>
  <label htmlFor="email">邮箱地址</label>
  <input 
    id="email" 
    type="email" 
    aria-describedby="email-help"
    aria-invalid={!!errors.email}
  />
  <p id="email-help">我们不会分享你的邮箱</p>
  {errors.email && (
    <p role="alert" className="text-red-500">
      {errors.email}
    </p>
  )}
</div>

// 必填字段
<label>
  邮箱 <span aria-hidden="true">*</span>
  <span className="sr-only">(必填)</span>
</label>
<input required aria-required="true" />

屏幕阅读器隐藏类

css
/* 视觉隐藏但屏幕阅读器可读 */
.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;
}

/* 聚焦时显示 */
.sr-only.focus:focus {
  position: static;
  width: auto;
  height: auto;
  padding: inherit;
  margin: inherit;
  overflow: visible;
  clip: auto;
  white-space: normal;
}

测试工具

工具用途
axe DevToolsChrome 扩展,自动检测问题
LighthouseChrome 内置,审计报告
WAVE在线检测工具
VoiceOvermacOS 内置屏幕阅读器
NVDAWindows 免费屏幕阅读器
tsx
// 使用 eslint-plugin-jsx-a11y 自动检测
// .eslintrc.js
module.exports = {
  extends: ['plugin:jsx-a11y/recommended'],
}

AI 协作指南

核心意图:让 AI 帮你检查和修复可访问性问题。

需求定义公式

  • 检查范围:[组件/页面] 的可访问性
  • 标准级别:WCAG 2.1 [A/AA/AAA]
  • 关注点:[键盘/屏幕阅读器/颜色对比度]

示例 Prompt

请检查这个模态框组件的可访问性:
1. 确保键盘可以打开、关闭、在内部导航
2. 添加正确的 ARIA 属性
3. 打开时焦点移入,关闭时焦点返回触发元素
4. ESC 键可关闭

验收清单

  • [ ] 所有功能可通过键盘操作
  • [ ] 焦点状态清晰可见
  • [ ] 图片有合适的替代文本
  • [ ] 表单有关联的标签
  • [ ] 使用语义化 HTML
  • [ ] 通过 axe/Lighthouse 检测