关于 accessibility-auditor
accessibility-auditor 为审查和改进 Web 无障碍体验的团队提供指导,介绍 WCAG 实践、常见修复、ARIA,以及自动化、键盘和屏幕阅读器测试。
主要功能
- 01WCAG 2.1 指导
- 02常见无障碍问题修复
- 03ARIA 属性与地标
- 04自动化测试清单
- 05键盘导航测试
- 06屏幕阅读器测试
适用场景
- 01按 WCAG 审查网站
- 02修复缺失标签或替代文本
- 03检查纯键盘操作
- 04使用屏幕阅读器测试页面
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ davila7/ claude-code-templates --skill accessibility-auditor安装后在 Claude Code 中输入/accessibility-auditor确认已加载。
详细介绍
无障碍审计器
为创建符合 WCAG 标准且能有效服务各种能力用户的无障碍 Web 体验提供全面指导。
何时使用此技能
在以下情况下使用此技能:
- 审计网站的无障碍合规性
- 实施 WCAG 2.1 AA 级或 AAA 级标准
- 修复无障碍违规和错误
- 使用屏幕阅读器(NVDA、JAWS、VoiceOver)进行测试
- 确保键盘导航正常工作
- 实施 ARIA 属性和地标
- 为 ADA 或 Section 508 合规审计做准备
- 设计包容性的用户体验
WCAG 2.1 原则(POUR)
1. 可感知
用户必须能够感知所呈现的信息。
2. 可操作
用户必须能够操作界面。
3. 可理解
用户必须能够理解信息和界面。
4. 健壮
内容必须足够健壮,能够与当前和未来的技术配合使用。
常见无障碍问题与修复
1. 图片缺少替代文本
❌ 问题:
<img src="/products/shoes.jpg">
✅ 解决方案:
<img src="/products/shoes.jpg" alt="Red Nike Air Max running shoes with white swoosh">
<img src="/decorative-pattern.svg" alt="" role="presentation">
<a href="/">
<img src="/logo.png" alt="Company Name - Home">
</a>
规则:
- 信息性图片:描述内容/功能
- 装饰性图片:使用空 alt(alt="")
- 功能性图片:描述操作
- 复杂图片:在附近提供详细描述
2. 颜色对比度低
❌ 问题:
/* Contrast ratio 2.5:1 - Fails WCAG */
.text {
color: #767676;
background: #ffffff;
}
✅ 解决方案:
/* Contrast ratio 4.5:1+ - Passes AA */
.text {
color: #595959;
background: #ffffff;
}
/* Contrast ratio 7:1+ - Passes AAA */
.text-high-contrast {
color: #333333;
background: #ffffff;
}
要求:
- 普通文本(< 18px):最低 4.5:1(AA),增强 7:1(AAA)
- 大号文本(≥ 18px 或 ≥ 14px 粗体):最低 3:1(AA),增强 4.5:1(AAA)
- UI 组件和图形:最低 3:1
3. 非语义化 HTML
❌ 问题:
<div class="button" onclick="submitForm()">Submit</div>
<div class="heading">Page Title</div>
<div class="nav-menu">...</div>
✅ 解决方案:
<button type="submit" onclick="submitForm()">Submit</button>
<h1>Page Title</h1>
<nav aria-label="Main navigation">...</nav>
语义化元素:
<button>用于按钮<a>用于链接<h1>-<h6>用于标题(层级)<nav>、<main>、<aside>、<article>、<section>用于地标<ul>、<ol>、<li>用于列表<table>、<th>、<td>用于表格数据
4. 表单缺少标签
❌ 问题:
<input type="email" placeholder="Enter your email">
✅ 解决方案:
<label for="email">Email Address</label>
<input type="email" id="email" name="email">
<label>
Email Address
<input type="email" name="email">
</label>
<label for="search" class="sr-only">Search</label>
<input type="text" id="search" placeholder="Search...">
最佳实践:
- 每个表单字段都必须有相关联的标签
- 标签应可见(不要依赖占位符)
- 仅在无法使用视觉标签时使用 aria-label
- 使用
<fieldset>和<legend>对相关字段进行分组
5. 键盘导航问题
❌ 问题:
<div onclick="handleClick()">Click me</div>
<a href="javascript:void(0)" onclick="doSomething()">Action</a>
✅ 解决方案:
<button onclick="handleClick()">Click me</button>
<div
role="button"
tabindex="0"
onclick="handleClick()"
onkeydown="handleKeyPress(event)"
>
Click me
</div>
<script>
function handleKeyPress(event) {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
handleClick();
}
}
</script>
键盘要求:
- 所有交互元素必须可通过键盘访问
- 可见的焦点指示器(轮廓或自定义样式)
- 逻辑的 Tab 顺序(与视觉流一致)
- 为重复内容提供跳转链接
- 无键盘陷阱(用户可以导航离开)
6. 缺少 ARIA 地标
❌ 问题:
<div class="header">...</div>
<div class="main-content">...</div>
<div class="sidebar">...</div>
<div class="footer">...</div>
✅ 解决方案:
<header role="banner">
<nav aria-label="Main navigation">...</nav>
</header>
<main role="main">
<h1>Page Title</h1>
<article>...</article>
</main>
<aside role="complementary" aria-label="Related articles">
...
</aside>
<footer role="contentinfo">
...
</footer>
常见地标:
banner- 站点页眉navigation- 导航菜单main- 主要内容(每页一个)complementary- 辅助内容contentinfo- 站点页脚search- 搜索功能form- 表单区域
7. 无法访问的模态框/对话框
❌ 问题:
<div class="modal">
<div class="content">
Modal content
<button onclick="closeModal()">Close</button>
</div>
</div>
✅ 解决方案:
<div
role="dialog"
aria-modal="true"
aria-labelledby="modal-title"
aria-describedby="modal-desc"
>
<h2 id="modal-title">Confirm Action</h2>
<p id="modal-desc">Are you sure you want to delete this item?</p>
<button onclick="confirmAction()">Confirm</button>
<button onclick="closeModal()">Cancel</button>
</div>
<script>
// Focus management
function openModal() {
const modal = document.querySelector('[role="dialog"]');
const focusableElements = modal.querySelectorAll(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
// Store previous focus
previousFocus = document.activeElement;
// Focus first element
focusableElements[0].focus();
// Trap focus
modal.addEventListener('keydown', trapFocus);
}
function closeModal() {
// Return focus
if (previousFocus) previousFocus.focus();
}
function trapFocus(event) {
if (event.key !== 'Tab') return;
const focusableElements = Array.from(
modal.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])')
);
const firstElement = focusableElements[0];
const lastElement = focusableElements[focusableElements.length - 1];
if (event.shiftKey && document.activeElement === firstElement) {
lastElement.focus();
event.preventDefault();
} else if (!event.shiftKey && document.activeElement === lastElement) {
firstElement.focus();
event.preventDefault();
}
}
</script>
模态框要求:
role="dialog"或role="alertdialog"aria-modal="true"以指示模态行为aria-labelledby指向标题aria-describedby用于描述(可选)- 焦点管理(捕获和恢复)
- 按 Escape 键关闭
- 阻止背景滚动
8. 缺少跳转链接
✅ 解决方案:
<a href="#main-content" class="skip-link">
Skip to main content
</a>
<header>
<nav>...</nav>
</header>
<main id="main-content" tabindex="-1">
</main>
<style>
.skip-link {
position: absolute;
top: -40px;
left: 0;
background: #000;
color: #fff;
padding: 8px;
text-decoration: none;
z-index: 100;
}
.skip-link:focus {
top: 0;
}
</style>
ARIA 最佳实践
ARIA 属性参考
状态:
aria-checked- 复选框/单选框状态aria-disabled- 禁用状态aria-expanded- 展开/折叠状态aria-hidden- 对辅助技术隐藏aria-pressed- 切换按钮状态aria-selected- 选中状态
属性:
aria-label- 无障碍名称aria-labelledby- 标签的 ID 引用aria-describedby- 描述的 ID 引用aria-live- 实时区域更新aria-required- 必填字段aria-invalid- 验证状态
实时区域
<div aria-live="polite" aria-atomic="true">
Item added to cart
</div>
<div aria-live="assertive" role="alert">
Error: Payment failed
</div>
<div role="status" aria-live="polite">
Saving changes...
</div>
自定义组件
手风琴:
<div class="accordion">
<button
aria-expanded="false"
aria-controls="panel-1"
id="accordion-1"
>
Section 1
</button>
<div id="panel-1" role="region" aria-labelledby="accordion-1" hidden>
Panel content
</div>
</div>
选项卡:
<div role="tablist" aria-label="Content sections">
<button
role="tab"
aria-selected="true"
aria-controls="panel-1"
id="tab-1"
>
Tab 1
</button>
<button
role="tab"
aria-selected="false"
aria-controls="panel-2"
id="tab-2"
tabindex="-1"
>
Tab 2
</button>
</div>
<div role="tabpanel" id="panel-1" aria-labelledby="tab-1">
Panel 1 content
</div>
<div role="tabpanel" id="panel-2" aria-labelledby="tab-2" hidden>
Panel 2 content
</div>
测试清单
自动化测试
- 运行 axe DevTools 或 WAVE 浏览器扩展
- 检查 HTML 验证(W3C Validator)
- 测试颜色对比度
- 验证标题层级
- 检查缺失的替代文本
手动测试
- 仅使用键盘导航整个网站(Tab、Enter、Escape、方向键)
- 使用屏幕阅读器测试(NVDA、JAWS 或 VoiceOver)
- 验证焦点指示器可见
- 检查表单验证消息是否被播报
- 测试模态框焦点陷阱
- 验证跳转链接可用
- 在 200% 浏览器缩放下测试
- 在不同视口尺寸下检查页面重排
- 禁用 JavaScript 并验证核心功能
- 在 Windows 高对比度模式下测试
屏幕阅读器测试
VoiceOver(Mac):
- 启用:Cmd + F5
- 导航:Control + Option + 方向键
- 全部朗读:Control + Option + A
NVDA(Windows):
- 导航:方向键(浏览模式)或 Tab(焦点模式)
- 全部朗读:NVDA + 向下箭头
- 元素列表:NVDA + F7
测试场景:
- 用户能否理解页面结构?
- 标题是否具有描述性且层级分明?
- 表单标签是否清晰且已关联?
- 错误消息是否被播报?
- 用户能否在没有视觉的情况下完成关键任务?
无障碍声明
在网站上包含:
# Accessibility Statement
We are committed to ensuring digital accessibility for people with disabilities. We continually improve the user experience for everyone and apply relevant accessibility standards.
## Conformance Status
This website is partially conformant with WCAG 2.1 Level AA. "Partially conformant" means that some parts of the content do not fully conform to the accessibility standard.
## Feedback
We welcome your feedback on the accessibility of this site. Please contact us:
- Email: [email protected]
- Phone: +1-555-0123
## Known Issues
- [List any known accessibility issues and planned fixes]
Last updated: [Date]
资源
工具:
- axe DevTools(浏览器扩展)
- WAVE(Web 无障碍评估工具)
- Lighthouse(Chrome DevTools)
- Colour Contrast Analyser
- 屏幕阅读器:NVDA、JAWS、VoiceOver
指南:
- WCAG 2.1:https://www.w3.org/WAI/WCAG21/quickref/
- ARIA Authoring Practices:https://www.w3.org/WAI/ARIA/apg/
无障碍不是可选项——它是创建包容性 Web 体验的基本要求。在每一个项目开始时就优先考虑它,而不是事后才想到。
评论
支持 Markdown