name: 可访问性审计专家 description: 网页可访问性专家,专注于WCAG合规、ARIA实现和包容性设计。在审计网站可访问性问题、实施WCAG 2.1 AA/AAA标准、使用屏幕阅读器测试或确保ADA合规时使用。精通语义HTML、键盘导航和辅助技术兼容性。
可访问性审计专家
创建符合WCAG标准并有效服务所有能力用户的网页体验的全面指南。
何时使用此技能
在以下情况使用此技能:
- 审计网站的可访问性合规性
- 实施WCAG 2.1 Level 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="红色Nike Air Max跑鞋,带有白色勾号">
<!-- 装饰性图像 -->
<img src="/decorative-pattern.svg" alt="" role="presentation">
<!-- 链接的徽标 -->
<a href="/">
<img src="/logo.png" alt="公司名称 - 首页">
</a>
规则:
- 信息性图像:描述内容/功能
- 装饰性图像:使用空alt(alt=“”)
- 功能性图像:描述操作
- 复杂图像:在附近提供详细描述
2. 低颜色对比度
❌ 问题:
/* 对比度比例2.5:1 - 不符合WCAG */
.text {
color: #767676;
background: #ffffff;
}
✅ 解决方案:
/* 对比度比例4.5:1+ - 符合AA级 */
.text {
color: #595959;
background: #ffffff;
}
/* 对比度比例7:1+ - 符合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()">提交</div>
<div class="heading">页面标题</div>
<div class="nav-menu">...</div>
✅ 解决方案:
<button type="submit" onclick="submitForm()">提交</button>
<h1>页面标题</h1>
<nav aria-label="主导航">...</nav>
语义元素:
<button>用于按钮<a>用于链接<h1>-<h6>用于标题(层级)<nav>,<main>,<aside>,<article>,<section>用于地标<ul>,<ol>,<li>用于列表<table>,<th>,<td>用于表格数据
4. 缺少表单标签
❌ 问题:
<input type="email" placeholder="输入您的邮箱">
✅ 解决方案:
<!-- 显式标签 -->
<label for="email">邮箱地址</label>
<input type="email" id="email" name="email">
<!-- 隐式标签 -->
<label>
邮箱地址
<input type="email" name="email">
</label>
<!-- 隐藏标签(适用于紧凑布局) -->
<label for="search" class="sr-only">搜索</label>
<input type="text" id="search" placeholder="搜索...">
最佳实践:
- 每个表单字段必须有相关标签
- 标签应可见(不要依赖占位符)
- 仅当视觉标签不可行时使用aria-label
- 使用
<fieldset>和<legend>分组相关字段
5. 键盘导航问题
❌ 问题:
<div onclick="handleClick()">点击我</div>
<a href="javascript:void(0)" onclick="doSomething()">操作</a>
✅ 解决方案:
<!-- 使用适当按钮 -->
<button onclick="handleClick()">点击我</button>
<!-- 如果必须使用div,使其可访问 -->
<div
role="button"
tabindex="0"
onclick="handleClick()"
onkeydown="handleKeyPress(event)"
>
点击我
</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="主导航">...</nav>
</header>
<main role="main">
<h1>页面标题</h1>
<article>...</article>
</main>
<aside role="complementary" aria-label="相关文章">
...
</aside>
<footer role="contentinfo">
...
</footer>
常见地标:
banner- 网站头部navigation- 导航菜单main- 主要内容(每页一个)complementary- 辅助内容contentinfo- 网站页脚search- 搜索功能form- 表单区域
7. 不可访问的模态框/对话框
❌ 问题:
<div class="modal">
<div class="content">
模态框内容
<button onclick="closeModal()">关闭</button>
</div>
</div>
✅ 解决方案:
<div
role="dialog"
aria-modal="true"
aria-labelledby="modal-title"
aria-describedby="modal-desc"
>
<h2 id="modal-title">确认操作</h2>
<p id="modal-desc">您确定要删除此项吗?</p>
<button onclick="confirmAction()">确认</button>
<button onclick="closeModal()">取消</button>
</div>
<script>
// 焦点管理
function openModal() {
const modal = document.querySelector('[role="dialog"]');
const focusableElements = modal.querySelectorAll(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
// 存储先前焦点
previousFocus = document.activeElement;
// 聚焦第一个元素
focusableElements[0].focus();
// 陷阱焦点
modal.addEventListener('keydown', trapFocus);
}
function closeModal() {
// 恢复焦点
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">
跳转到主要内容
</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">
已添加到购物车
</div>
<!-- 断言:立即中断 -->
<div aria-live="assertive" role="alert">
错误:支付失败
</div>
<!-- 状态消息 -->
<div role="status" aria-live="polite">
正在保存更改...
</div>
自定义组件
手风琴:
<div class="accordion">
<button
aria-expanded="false"
aria-controls="panel-1"
id="accordion-1"
>
第1节
</button>
<div id="panel-1" role="region" aria-labelledby="accordion-1" hidden>
面板内容
</div>
</div>
标签页:
<div role="tablist" aria-label="内容部分">
<button
role="tab"
aria-selected="true"
aria-controls="panel-1"
id="tab-1"
>
标签页1
</button>
<button
role="tab"
aria-selected="false"
aria-controls="panel-2"
id="tab-2"
tabindex="-1"
>
标签页2
</button>
</div>
<div role="tabpanel" id="panel-1" aria-labelledby="tab-1">
面板1内容
</div>
<div role="tabpanel" id="panel-2" aria-labelledby="tab-2" hidden>
面板2内容
</div>
测试清单
自动化测试
- [ ] 运行axe DevTools或WAVE浏览器扩展
- [ ] 检查HTML验证(W3C验证器)
- [ ] 测试颜色对比度比例
- [ ] 验证标题层次
- [ ] 检查缺少替代文本
手动测试
- [ ] 仅使用键盘导航整个网站(Tab、Enter、Escape、方向键)
- [ ] 使用屏幕阅读器测试(NVDA、JAWS或VoiceOver)
- [ ] 验证焦点指示器是否可见
- [ ] 检查表单验证消息是否被宣布
- [ ] 测试模态框焦点陷阱
- [ ] 验证跳过链接是否工作
- [ ] 测试浏览器缩放至200%
- [ ] 检查不同视口大小下的页面重排
- [ ] 禁用JavaScript并验证核心功能
- [ ] 测试Windows高对比度模式
屏幕阅读器测试
VoiceOver(Mac):
- 启用:Cmd + F5
- 导航:Control + Option + 方向键
- 阅读全部:Control + Option + A
NVDA(Windows):
- 导航:方向键(浏览模式)或Tab(焦点模式)
- 阅读全部:NVDA + 向下键
- 元素列表:NVDA + F7
测试场景:
- 用户能理解页面结构吗?
- 标题是否描述性且层次化?
- 表单标签是否清晰且相关?
- 错误消息是否被宣布?
- 用户能否在没有视觉的情况下完成关键任务?
可访问性声明
在网站上包含:
# 可访问性声明
我们致力于确保数字可访问性,为残障人士提供支持。我们持续改进用户体验并应用相关可访问性标准。
## 合规状态
本网站部分符合WCAG 2.1 Level AA。“部分符合”意味着某些内容未完全符合可访问性标准。
## 反馈
我们欢迎您对本网站可访问性的反馈。请通过以下方式联系我们:
- 邮箱:accessibility@example.com
- 电话:+1-555-0123
## 已知问题
- [列出任何已知可访问性问题及计划修复]
最后更新:[日期]
资源
工具:
- axe DevTools(浏览器扩展)
- WAVE(网页可访问性评估工具)
- Lighthouse(Chrome DevTools)
- 颜色对比度分析器
- 屏幕阅读器:NVDA、JAWS、VoiceOver
指南:
- WCAG 2.1:https://www.w3.org/WAI/WCAG21/quickref/
- ARIA创作实践:https://www.w3.org/WAI/ARIA/apg/
可访问性不是可选的——它是创建包容性网页体验的基本要求。从每个项目开始就优先考虑,而不是事后补丁。