by wshobson
无障碍审计是复杂的,容易遗漏关键问题。此技能提供 WCAG 2.2 检查清单、测试指导和网站及应用程序的修复模式。
1. 打开 Claude 聊天界面
2. 点击下方 "📋 复制" 按钮
3. 粘贴到 Claude 聊天框中并发送
4. 输入 "使用 wcag-audit-patterns 技能" 开始使用
=== wcag-audit-patterns 技能 === 作者: wshobson 描述: 无障碍审计是复杂的,容易遗漏关键问题。此技能提供 WCAG 2.2 检查清单、测试指导和网站及应用程序的修复模式。 使用方法: 1. 调用技能: "使用 wcag-audit-patterns 技能" 2. 提供相关信息: 根据技能要求提供必要参数 3. 查看结果: 技能会返回处理结果 示例: "使用 wcag-audit-patterns 技能,帮我分析一下这段代码"
这种方法适用于所有 Claude 用户,不需要安装额外工具。
documentation
safe
Comprehensive guide to auditing web content against WCAG 2.2 guidelines with actionable remediation strategies.
| Level | Description | Required For |
|---|---|---|
| A | Minimum accessibility | Legal baseline |
| AA | Standard conformance | Most regulations |
| AAA | Enhanced accessibility | Specialized needs |
Perceivable: Can users perceive the content?
Operable: Can users operate the interface?
Understandable: Can users understand the content?
Robust: Does it work with assistive tech?
Critical (Blockers):
├── Missing alt text for functional images
├── No keyboard access to interactive elements
├── Missing form labels
└── Auto-playing media without controls
Serious:
├── Insufficient color contrast
├── Missing skip links
├── Inaccessible custom widgets
└── Missing page titles
Moderate:
├── Missing language attribute
├── Unclear link text
├── Missing landmarks
└── Improper heading hierarchy
## 1.1 Text Alternatives
### 1.1.1 Non-text Content (Level A)
- [ ] All images have alt text
- [ ] Decorative images have alt=""
- [ ] Complex images have long descriptions
- [ ] Icons with meaning have accessible names
- [ ] CAPTCHAs have alternatives
Check:
```html
<!-- Good -->
<img src="chart.png" alt="Sales increased 25% from Q1 to Q2">
<img src="decorative-line.png" alt="">
<!-- Bad -->
<img src="chart.png">
<img src="decorative-line.png" alt="decorative line">
Check:
<!-- Heading hierarchy -->
<h1>Page Title</h1>
<h2>Section</h2>
<h3>Subsection</h3>
<h2>Another Section</h2>
<!-- Table headers -->
<table>
<thead>
<tr><th scope="col">Name</th><th scope="col">Price</th></tr>
</thead>
</table>
Tools: WebAIM Contrast Checker, axe DevTools
### Operable (Principle 2)
```markdown
## 2.1 Keyboard Accessible
### 2.1.1 Keyboard (Level A)
- [ ] All functionality keyboard accessible
- [ ] No keyboard traps
- [ ] Tab order is logical
- [ ] Custom widgets are keyboard operable
Check:
```javascript
// Custom button must be keyboard accessible
<div role="button" tabindex="0"
onkeydown="if(event.key === 'Enter' || event.key === ' ') activate()">
@media (prefers-reduced-motion: reduce) {
* {
animation: none !important;
transition: none !important;
}
}
<a href="#main" class="skip-link">Skip to main content</a>
<main id="main">...</main>
<!-- Bad -->
<a href="report.pdf">Click here</a>
<!-- Good -->
<a href="report.pdf">Download Q4 Sales Report (PDF)</a>
:focus {
outline: 3px solid #005fcc;
outline-offset: 2px;
}
### Understandable (Principle 3)
```markdown
## 3.1 Readable
### 3.1.1 Language of Page (Level A)
- [ ] HTML lang attribute set
- [ ] Language correct for content
```html
<html lang="en">
<p>The French word <span lang="fr">bonjour</span> means hello.</p>
<input aria-describedby="email-error" aria-invalid="true">
<span id="email-error" role="alert">Please enter valid email</span>
### Robust (Principle 4)
```markdown
## 4.1 Compatible
### 4.1.1 Parsing (Level A) - Obsolete in WCAG 2.2
- [ ] Valid HTML (good practice)
- [ ] No duplicate IDs
- [ ] Complete start/end tags
### 4.1.2 Name, Role, Value (Level A)
- [ ] Custom widgets have accessible names
- [ ] ARIA roles correct
- [ ] State changes announced
```html
<!-- Accessible custom checkbox -->
<div role="checkbox"
aria-checked="false"
tabindex="0"
aria-labelledby="label">
</div>
<span id="label">Accept terms</span>
<div role="status" aria-live="polite">
3 items added to cart
</div>
<div role="alert" aria-live="assertive">
Error: Form submission failed
</div>
## Automated Testing
```javascript
// axe-core integration
const axe = require('axe-core');
async function runAccessibilityAudit(page) {
await page.addScriptTag({ path: require.resolve('axe-core') });
const results = await page.evaluate(async () => {
return await axe.run(document, {
runOnly: {
type: 'tag',
values: ['wcag2a', 'wcag2aa', 'wcag21aa', 'wcag22aa']
}
});
});
return {
violations: results.violations,
passes: results.passes,
incomplete: results.incomplete
};
}
// Playwright test example
test('should have no accessibility violations', async ({ page }) => {
await page.goto('/');
const results = await runAccessibilityAudit(page);
expect(results.violations).toHaveLength(0);
});
# CLI tools
npx @axe-core/cli https://example.com
npx pa11y https://example.com
lighthouse https://example.com --only-categories=accessibility
<!-- Before -->
<input type="email" placeholder="Email">
<!-- After: Option 1 - Visible label -->
<label for="email">Email address</label>
<input id="email" type="email">
<!-- After: Option 2 - aria-label -->
<input type="email" aria-label="Email address">
<!-- After: Option 3 - aria-labelledby -->
<span id="email-label">Email</span>
<input type="email" aria-labelledby="email-label">
/* Before: 2.5:1 contrast */
.text { color: #767676; }
/* After: 4.5:1 contrast */
.text { color: #595959; }
/* Or add background */
.text {
color: #767676;
background: #000;
}
// Make custom element keyboard accessible
class AccessibleDropdown extends HTMLElement {
connectedCallback() {
this.setAttribute('tabindex', '0');
this.setAttribute('role', 'combobox');
this.setAttribute('aria-expanded', 'false');
this.addEventListener('keydown', (e) => {
switch (e.key) {
case 'Enter':
case ' ':
this.toggle();
e.preventDefault();
break;
case 'Escape':
this.close();
break;
case 'ArrowDown':
this.focusNext();
e.preventDefault();
break;
case 'ArrowUp':
this.focusPrevious();
e.preventDefault();
break;
}
});
}
}
View Count
0
Download Count
0
Favorite Count
0
Quality Score
69