mcpField
A
accessibility

accessibility

github.com/thedesignproject设计与 UI98250 次安装9 周前更新
代码仓库

关于 accessibility

面向设计师和开发者的无障碍指南,依据 WCAG 2.2 与 Lighthouse 审计涵盖设计原则、实现模式和测试清单。

主要功能

  1. 01WCAG 2.2 原则与合规等级
  2. 02键盘操作与焦点管理
  3. 03颜色对比和文本替代
  4. 04表单、错误与 ARIA 模式
  5. 05自动化及手动测试清单

适用场景

  1. 01检查页面是否符合无障碍要求
  2. 02实现键盘可操作的界面
  3. 03审查表单和错误提示
  4. 04规划发布前的无障碍测试

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/thedesignproject/agent-skills --skill accessibility

安装后在 Claude Code 中输入/accessibility确认已加载。

附带文件references/A11Y-PATTERNS.mdreferences/WCAG.md

详细介绍

无障碍访问(a11y)

基于 WCAG 2.2 和 Lighthouse 无障碍审查的综合无障碍指南。目标是让所有人都能使用内容,包括残障人士。

WCAG 原则:POUR

原则描述
Perceivable(可感知)内容可通过不同感官感知
Operable(可操作)所有用户都能操作界面
Understandable(可理解)内容和界面易于理解
Robust(健壮)内容可与辅助技术配合使用

合规等级

等级要求目标
A最低无障碍要求必须通过
AA标准合规应通过(许多司法辖区的法律要求)
AAA增强无障碍访问最好达到

可感知

文本替代内容(1.1)

图片需要替代文本:


<img src="chart.png">


<img src="chart.png" alt="Bar chart showing 40% increase in Q3 sales">


<img src="decorative-border.png" alt="" role="presentation">


<figure>
  <img src="infographic.png" alt="2024 market trends infographic" 
       aria-describedby="infographic-desc">
  <figcaption id="infographic-desc">
    
  </figcaption>
</figure>

图标按钮需要无障碍名称:


<button><svg></svg></button>


<button aria-label="Open menu">
  <svg aria-hidden="true"></svg>
</button>


<button>
  <svg aria-hidden="true"></svg>
  <span class="visually-hidden">Open menu</span>
</button>

视觉隐藏类:

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
颜色对比度(1.4.3、1.4.6)
文本大小AA 最低要求AAA 增强要求
普通文本(< 18px / < 14px 粗体)4.5:17:1
大号文本(≥ 18px / ≥ 14px 粗体)3:14.5:1
UI 组件和图形3:13:1
/* ❌ Low contrast (2.5:1) */
.low-contrast {
  color: #999;
  background: #fff;
}

/* ✅ Sufficient contrast (7:1) */
.high-contrast {
  color: #333;
  background: #fff;
}

/* ✅ Focus states need contrast too (3:1 against background, WCAG 1.4.11) */
:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

不要只依赖颜色传达信息:


<input class="error-border">
<style>.error-border { border-color: red; }</style>


<div class="field-error">
  <input aria-invalid="true" aria-describedby="email-error">
  <span id="email-error" class="error-message">
    <svg aria-hidden="true"></svg>
    Please enter a valid email address
  </span>
</div>
媒体替代内容(1.2)

<video controls>
  <source src="video.mp4" type="video/mp4">
  <track kind="captions" src="captions.vtt" srclang="en" label="English" default>
  <track kind="descriptions" src="descriptions.vtt" srclang="en" label="Descriptions">
</video>


<audio controls>
  <source src="podcast.mp3" type="audio/mp3">
</audio>
<details>
  <summary>Transcript</summary>
  <p>Full transcript text...</p>
</details>

可操作

键盘可访问性(2.1)

所有功能都必须支持键盘操作。 优先使用原生交互元素——<button>、<a href> 和表单控件会自动处理 Enter/Space 键激活、焦点和辅助技术语义。只有无法使用原生元素时,才手动添加键盘处理逻辑。


<div class="card" onclick="handleAction()">Open</div>


<button type="button" onclick="handleAction()">Open</button>
// ✅ When you MUST use a non-interactive element (e.g. div with role="button"),
// make it focusable AND handle keyboard activation. Do NOT add this to a native
// <button> — Enter/Space already fire click, so you'd double-trigger.
element.setAttribute('role', 'button');
element.setAttribute('tabindex', '0');
element.addEventListener('click', handleAction);
element.addEventListener('keydown', (e) => {
  if (e.key === 'Enter' || e.key === ' ') {
    e.preventDefault();
    handleAction();
  }
});

不得设置键盘陷阱。 用户必须能够使用 Tab 键进入和离开每个组件。对话框请使用模态框焦点陷阱模式——原生 <dialog> 元素会自动处理这一点。

焦点可见(2.4.7)
/* ❌ Never remove focus outlines */
*:focus { outline: none; }

/* ✅ Use :focus-visible for keyboard-only focus */
:focus {
  outline: none;
}

:focus-visible {
  outline: 2px solid currentColor; /* inherits text color → already contrast-checked */
  outline-offset: 2px;
}

/* ✅ Or pick a brand color and verify ≥3:1 contrast against every background it lands on */
button:focus-visible {
  box-shadow: 0 0 0 3px rgba(0, 95, 204, 0.5);
}
焦点不被遮挡(2.4.11)——2.2 新增

当元素获得键盘焦点时,不得被粘性页眉、页脚或重叠面板等其他由作者创建的内容完全遮挡。在 AAA 等级(2.4.12)下,焦点元素的任何部分都不得被遮挡。

/* ✅ Account for sticky headers when scrolling to focused elements */
:target {
  scroll-margin-top: 80px;
}

/* ✅ Ensure focused items clear fixed/sticky bars */
:focus {
  scroll-margin-top: 80px;
  scroll-margin-bottom: 60px;
}
跳过链接(2.4.1)

提供跳过链接,让键盘用户可以跳过重复的导航内容。完整标记和样式请参见跳过链接模式。

目标尺寸(2.5.8)——2.2 新增

交互目标的尺寸必须至少为 24 × 24 CSS 像素(AA)。例外情况:行内文本链接、尺寸由浏览器控制的元素,以及在边界框中心绘制直径为 24px 的圆后不会与其他目标重叠的目标。

/* ✅ Minimum target size */
button,
[role="button"],
input[type="checkbox"] + label,
input[type="radio"] + label {
  min-width: 24px;
  min-height: 24px;
}

/* ✅ Comfortable target size (recommended 44×44) */
.touch-target {
  min-width: 44px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
拖动操作(2.5.7)——2.2 新增

任何需要拖动的操作都必须提供单指针替代方式(例如按钮、输入框)。可排序列表示例请参见拖动操作模式。

时间限制(2.2)
// Allow users to extend time limits
function showSessionWarning() {
  const modal = createModal({
    title: 'Session Expiring',
    content: 'Your session will expire in 2 minutes.',
    actions: [
      { label: 'Extend session', action: extendSession },
      { label: 'Log out', action: logout }
    ],
    timeout: 120000
  });
}
动效(2.3)
/* Respect reduced motion preference */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

可理解

页面语言(3.1.1)

<html>


<html lang="en">


<p>The French word for hello is <span lang="fr">bonjour</span>.</p>
导航一致性(3.2.3)

<nav aria-label="Main">
  <ul>
    <li><a href="/" aria-current="page">Home</a></li>
    <li><a href="/products">Products</a></li>
    <li><a href="/about">About</a></li>
  </ul>
</nav>
帮助一致性(3.2.6)——2.2 新增

如果某种帮助方式(联系信息、聊天工具、常见问题链接、自助选项)在多个页面中重复出现,则每次都必须按相同的相对顺序显示。依赖固定位置的用户不应每次都在页面上寻找帮助。

表单标签(3.3.2)

每个输入框都需要以编程方式关联的标签。有关显式、隐式和说明性示例,请参见表单标签模式。

错误处理(3.3.1、3.3.3)

使用 role="alert" 或 aria-live 向屏幕阅读器播报错误,在无效字段上设置 aria-invalid="true",并在提交时将焦点移至第一个错误处。完整标记和 JS 请参见错误处理模式。

冗余输入(3.3.7)— 2.2 版新增

不要强迫用户在同一会话中重复输入已提供的信息。自动填入之前步骤中的信息,或让用户从之前输入过的值中选择。例外情况:安全性重新确认以及已过期的内容。


<fieldset>
  <legend>Shipping address</legend>
  <label>
    <input type="checkbox" id="same-as-billing" checked>
    Same as billing address
  </label>
  
</fieldset>
易于使用的身份验证(3.3.8)— 2.2 版新增

登录流程不得依赖认知功能测试(例如记住密码、解谜),除非至少满足以下一项:

  • 提供复制粘贴或自动填充机制
  • 提供其他方式(例如通行密钥、SSO、电子邮件链接)
  • 测试使用物体识别或个人内容(仅适用于 AA;AAA 不包含此例外)

<input type="password" id="password" autocomplete="current-password">


<button type="button">Sign in with passkey</button>
<button type="button">Email me a login link</button>

稳健性

ARIA 用法(4.1.2)

优先使用原生元素:


<div role="button" tabindex="0">Click me</div>


<button>Click me</button>


<div role="checkbox" aria-checked="false">Option</div>


<label><input type="checkbox"> Option</label>

**需要使用 ARIA 时,**请使用正确的角色和状态。完整的标签列表示例请参阅 ARIA 标签页模式。

实时区域(4.1.3)

使用 aria-live 区域播报动态内容变化,而不移动焦点。有关标记和 showNotification() 助手函数,请参阅实时区域模式。


测试清单

自动化测试
# Lighthouse accessibility audit
npx lighthouse https://example.com --only-categories=accessibility

# axe-core
npm install @axe-core/cli -g
axe https://example.com
手动测试
  • 键盘导航: 使用 Tab 遍历整个页面,并使用 Enter/Space 激活
  • 屏幕阅读器: 使用 VoiceOver(Mac)、NVDA(Windows)或 TalkBack(Android)进行测试
  • 缩放: 内容在 200% 缩放下仍可使用
  • 高对比度: 使用 Windows 高对比度模式进行测试
  • 减少动态效果: 使用 prefers-reduced-motion: reduce 进行测试
  • 焦点顺序: 顺序合理,并符合视觉顺序
  • 目标尺寸: 交互元素至少达到 24×24px

VoiceOver 和 NVDA 快捷键请参阅屏幕阅读器命令参考。


按影响程度分类的常见问题

严重(立即修复)
  1. 表单缺少标签
  2. 图片缺少替代文本
  3. 颜色对比度不足
  4. 键盘陷阱
  5. 缺少焦点指示器
较严重(上线前修复)
  1. 缺少页面语言声明
  2. 缺少标题结构
  3. 链接文本描述不清
  4. 媒体自动播放
  5. 缺少跳过链接
中等(尽快修复)
  1. 图标缺少 ARIA 标签
  2. 导航不一致
  3. 未能识别错误
  4. 计时功能缺少控件
  5. 缺少地标区域

参考资料

评论

支持 Markdown