wcag-auditor
Skill20 starsChanged 10 months agoMITView on GitHub
This skill provides WCAG 2.1 accessibility audit capabilities, including criteria definitions, check implementations, and scoring logic. Systematically evaluate web pages against WCAG 2.1 Level A and AA success criteria to identify accessibility barriers and provide remediation guidance. WCAG is organized around four principles (POUR): - Perceivable: Information must be presentable to users - Operable: Interface must be usable - Understandable: Information and operation must be understandable - Robust: Content must be interpretable by assistive technologies This skill implements Level A…
2 other projects use a version of this.
Adopted by
Most recently taken up by
- ImYourBoyRoy/Portable_Web_toolkittheir own version, first seen Jul 26, 2026
- petro-nazarenko/claude-skillstheir own version, first seen Apr 10, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- ImYourBoyRoy/Portable_Web_toolkit★ 2same name
- petro-nazarenko/claude-skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository13 other files it gives its agents.
- ab-testingSkill
- cookie-auditorSkill
- critical-pathsSkill
- form-fuzzerSkill
- github-prSkill
- link-checkerSkill
- network-throttlingSkill
- persona-generatorSkill
- screenshot-annotatorSkill
- session-recorderSkill
- smoke-testingSkill
- stripe-checkoutSkill
- user-testingSkill
The file
We split this skill into the rules it gives an agent
12 rules. About 0 are common, 12 are distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈12
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 65
All interactive elements are reachable
- Distinctive: line 67
No focus traps exist
- Distinctive: line 74
Requirement: All non-text content has a text alternative.
- Distinctive: line 88
Pass if: No violations found
- Distinctive: line 127
Requirement: All functionality is available via keyboard.
- Distinctive: line 138
Check: After focusing each element, verify Tab/Shift+Tab moves focus.
- Distinctive: line 180
Requirement: Default human language is programmatically determinable.
- Distinctive: line 222
Requirement: No duplicate IDs, elements properly nested.
- Distinctive: line 248
Check via browser_snapshot: Verify custom widgets have appropriate ARIA.
- Distinctive: line 294
Check: Verify button borders, input borders, focus indicators have sufficient contrast.
- Distinctive: line 392
When violations are found, annotate them:
- Distinctive: line 396
Add red box annotation with criterion ID as label
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
WCAG Auditor Skill
This skill provides WCAG 2.1 accessibility audit capabilities, including criteria definitions, check implementations, and scoring logic.
Purpose
Systematically evaluate web pages against WCAG 2.1 Level A and AA success criteria to identify accessibility barriers and provide remediation guidance.
WCAG 2.1 Overview
WCAG is organized around four principles (POUR):
- Perceivable: Information must be presentable to users
- Operable: Interface must be usable
- Understandable: Information and operation must be understandable
- Robust: Content must be interpretable by assistive technologies
Conformance Levels
| Level | Description | Requirements |
| A | Minimum | Essential accessibility |
| AA | Standard | Most common requirement |
| AAA | Enhanced | Highest accessibility |
This skill implements Level A and AA checks.
Check Implementation Guide
Using browser_evaluate for DOM Checks
Most WCAG checks can be performed via JavaScript evaluation:
// Example: Check for images without alt text
(function() {
const images = document.querySelectorAll('img');
const violations = [];
images.forEach(function(img) {
if (!img.hasAttribute('alt')) {
violations.push({
element: img.outerHTML.substring(0, 100),
selector: getSelector(img)
});
}
});
return { passed: violations.length === 0, violations: violations };
})();Using browser_snapshot for Accessibility Tree
The accessibility snapshot provides:
- ARIA roles and properties
- Accessible names
- Focusable elements
- Heading structure
Parse the snapshot to verify semantic structure.
Using browser_press_key for Keyboard Tests
Tab through the page to verify:
- All interactive elements are reachable
- Focus order is logical
- No focus traps exist
Criteria Reference
Level A Criteria
1.1.1 Non-text Content
Requirement: All non-text content has a text alternative.
Check:
// Find images without alt
const imagesWithoutAlt = document.querySelectorAll('img:not([alt])');
// Find inputs type=image without alt
const imageInputsWithoutAlt = document.querySelectorAll('input[type="image"]:not([alt])');
// Find area elements without alt
const areasWithoutAlt = document.querySelectorAll('area:not([alt])');Pass if: No violations found Severity: Critical (for functional images), Minor (for decorative)
1.3.1 Info and Relationships
Requirement: Information, structure, and relationships are programmatically determinable.
Check:
// Check heading hierarchy
const headings = document.querySelectorAll('h1, h2, h3, h4, h5, h6');
let lastLevel = 0;
const violations = [];
headings.forEach(function(h) {
const level = parseInt(h.tagName[1]);
if (level > lastLevel + 1) {
violations.push({ element: h, issue: 'Skipped heading level' });
}
lastLevel = level;
});
// Check form labels
const inputs = document.querySelectorAll('input, select, textarea');
inputs.forEach(function(input) {
if (!input.labels || input.labels.length === 0) {
if (!input.getAttribute('aria-label') && !input.getAttribute('aria-labelledby')) {
violations.push({ element: input, issue: 'Missing label' });
}
}
});Severity: Major
2.1.1 Keyboard
Requirement: All functionality is available via keyboard.
Check: Tab through page and verify all interactive elements are reachable.
Severity: Critical
2.1.2 No Keyboard Trap
Requirement: Focus can move away from any component.
Check: After focusing each element, verify Tab/Shift+Tab moves focus.
Severity: Critical
2.4.1 Bypass Blocks
Requirement: Mechanism to bypass repeated content.
Check:
// Look for skip links
const skipLink = document.querySelector('a[href^="#main"], a[href^="#content"], .skip-link');
// Look for landmark regions
const landmarks = document.querySelectorAll('main, [role="main"], nav, [role="navigation"]');
return { hasSkipLink: !!skipLink, hasLandmarks: landmarks.length > 0 };Severity: Major
2.4.2 Page Titled
Requirement: Web pages have titles describing topic or purpose.
Check:
const title = document.title;
return {
hasTitle: title && title.trim().length > 0,
title: title,
isDescriptive: title && title.length > 5 && !title.match(/^(untitled|home|page)$/i)
};Severity: Minor
3.1.1 Language of Page
Requirement: Default human language is programmatically determinable.
Check:
const htmlLang = document.documentElement.getAttribute('lang');
const validLangs = ['en', 'es', 'fr', 'de', 'it', 'pt', 'zh', 'ja', 'ko', 'ar', 'ru'];
return {
hasLang: !!htmlLang,
lang: htmlLang,
isValid: validLangs.some(function(l) { return htmlLang && htmlLang.startsWith(l); })
};Severity: Minor
3.3.2 Labels or Instructions
Requirement: Labels or instructions provided for user input.
Check:
const formFields = document.querySelectorAll('input:not([type="hidden"]), select, textarea');
const violations = [];
formFields.forEach(function(field) {
const hasLabel = field.labels && field.labels.length > 0;
const hasAriaLabel = field.getAttribute('aria-label');
const hasAriaLabelledby = field.getAttribute('aria-labelledby');
const hasTitle = field.getAttribute('title');
if (!hasLabel && !hasAriaLabel && !hasAriaLabelledby && !hasTitle) {
violations.push({ element: field, issue: 'No accessible label' });
}
});Severity: Critical
4.1.1 Parsing
Requirement: No duplicate IDs, elements properly nested.
Check:
const allIds = document.querySelectorAll('[id]');
const idMap = {};
const duplicates = [];
allIds.forEach(function(el) {
const id = el.id;
if (idMap[id]) {
duplicates.push(id);
}
idMap[id] = true;
});
return { hasDuplicates: duplicates.length > 0, duplicates: duplicates };Severity: Minor
4.1.2 Name, Role, Value
Requirement: UI components have accessible name, role, and state.
Check via browser_snapshot: Verify custom widgets have appropriate ARIA.
Severity: Critical
Level AA Criteria
1.4.3 Contrast (Minimum)
Requirement: Text has contrast ratio of at least 4.5:1 (3:1 for large text).
Check:
function getLuminance(r, g, b) {
var a = [r, g, b].map(function(v) {
v /= 255;
return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
});
return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
}
function getContrastRatio(l1, l2) {
var lighter = Math.max(l1, l2);
var darker = Math.min(l1, l2);
return (lighter + 0.05) / (darker + 0.05);
}
// Check text elements
var textElements = document.querySelectorAll('p, span, a, h1, h2, h3, h4, h5, h6, li, td, th, label');
var violations = [];
textElements.forEach(function(el) {
var style = window.getComputedStyle(el);
var color = style.color;
var bgColor = style.backgroundColor;
// ... calculate contrast
});Severity: Major
1.4.11 Non-text Contrast
Requirement: UI components have 3:1 contrast ratio.
Check: Verify button borders, input borders, focus indicators have sufficient contrast.
Severity: Major
2.4.7 Focus Visible
Requirement: Keyboard focus indicator is visible.
Check: Tab through elements and verify focus styles are visible.
Severity: Major
Scoring Logic
Calculate Scores
function calculateScore(results) {
var levelA = results.filter(function(r) { return r.level === 'A'; });
var levelAA = results.filter(function(r) { return r.level === 'AA'; });
var aScore = (levelA.filter(function(r) { return r.passed; }).length / levelA.length) * 100;
var aaScore = (levelAA.filter(function(r) { return r.passed; }).length / levelAA.length) * 100;
var overall = (results.filter(function(r) { return r.passed; }).length / results.length) * 100;
return {
levelA: Math.round(aScore),
levelAA: Math.round(aaScore),
overall: Math.round(overall),
grade: getGrade(overall)
};
}
function getGrade(score) {
if (score >= 90) return 'A';
if (score >= 80) return 'B';
if (score >= 70) return 'C';
if (score >= 60) return 'D';
return 'F';
}Remediation Guidance
Common Fixes
| Issue | Fix |
| Missing alt text | Add descriptive alt attribute |
| Missing form labels | Associate label with for attribute |
| Low contrast | Increase color difference |
| No skip link | Add "Skip to main content" link |
| Missing lang | Add lang attribute to html element |
| Keyboard trap | Ensure Tab/Escape can exit |
| No focus visible | Add :focus styles with outline |
Code Examples
Adding alt text:
<!-- Before -->
<img src="chart.png">
<!-- After -->
<img src="chart.png" alt="Sales chart showing 20% growth in Q4">Adding form label:
<!-- Before -->
<input type="email" placeholder="Email">
<!-- After -->
<label for="email">Email address</label>
<input type="email" id="email">Adding skip link:
<a href="#main-content" class="skip-link">Skip to main content</a>
<!-- ... header/nav ... -->
<main id="main-content">Improving contrast:
/* Before: 2.5:1 ratio */
.text { color: #999; background: #fff; }
/* After: 4.6:1 ratio */
.text { color: #666; background: #fff; }Integration with Screenshot Annotator
When violations are found, annotate them:
- For each violation with identifiable element
- Get element position
- Add red box annotation with criterion ID as label
- Take screenshot
- Include in report
Report Templates
See commands/wcag-audit.md for full report format templates.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

