Accessibility
Security skills for AI coding agents. Install once, write secure code every time.
npx -y skills add hereshecodes/secureskills --skill accessibilityAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use when writing frontend UI, HTML, components, or forms
SKILL.md
3.6 KB, as published. Nobody here has run it
Accessibility (WCAG 2.1 AA)
Accessibility is not optional. Every component, every page, every form. If it's not usable for everyone, it's broken.
Related: input-validation, xss-csrf, security-context
Rule 1: Every Input Needs a Label
No exceptions. Screen readers cannot describe unlabeled inputs.
<!-- WRONG — input with no label -->
<input type="email" placeholder="Email">
<!-- RIGHT — label with matching for/id -->
<label for="email">Email</label>
<input id="email" type="email" autocomplete="email" aria-required="true">
Rule 2: Buttons Describe Their Action
Icon-only buttons must have an aria-label. "X" is not a description.
<!-- WRONG — screen reader says "button" -->
<button><svg>...</svg></button>
<!-- RIGHT — screen reader says "Close dialog" -->
<button aria-label="Close dialog"><svg aria-hidden="true">...</svg></button>
Rule 3: Use Semantic HTML
Use the right element for the job. Divs are not buttons. Spans are not links.
<!-- WRONG — div pretending to be a button -->
<div class="btn" onclick="save()">Save</div>
<!-- RIGHT — actual button (keyboard accessible, focusable, announced correctly) -->
<button type="button" onclick="save()">Save</button>
Rule 4: Color Is Not the Only Indicator
15-20% of users have some form of color vision deficiency.
<!-- WRONG — only color indicates error -->
<span style="color: red">Error</span>
<!-- RIGHT — icon + color + role for screen readers -->
<span role="alert" class="error">
<svg aria-hidden="true">...</svg> Error: Email is required
</span>
Rule 5: Maintain Heading Hierarchy
Never skip heading levels. One h1 per page.
<!-- WRONG — skips h2 -->
<h1>Dashboard</h1>
<h3>Recent Activity</h3>
<!-- RIGHT — sequential levels -->
<h1>Dashboard</h1>
<h2>Recent Activity</h2>
Rule 6: All Interactive Elements Are Keyboard Accessible
Tab, Enter, Escape, Arrow keys. If you can click it, you can keyboard it.
// WRONG — only handles click
element.addEventListener('click', handler);
// RIGHT — handles click AND keyboard
element.addEventListener('click', handler);
element.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') handler(e);
});
// Or better: use <button> which handles this automatically
Rule 7: Announce Dynamic Content
When content changes without a page load, screen readers need to know.
<!-- Status updates -->
<div role="status" aria-live="polite">3 results found</div>
<!-- Error alerts -->
<div role="alert">Payment failed. Please try again.</div>
Rule 8: Respect Motion Preferences
Some users get physically ill from animations.
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
Quick Reference
| Do | Don't |
|---|---|
| Label every form input | Use placeholder as the only label |
| Add aria-label to icon-only buttons | Leave buttons without accessible names |
Use <button> and <a> for interactions | Use <div onclick> or <span onclick> |
| Pair color with icons/text | Use color as the only indicator |
| Keep heading hierarchy sequential | Skip heading levels |
| Support keyboard navigation | Make click-only interactions |
Use aria-live for dynamic updates | Silently change content |
Respect prefers-reduced-motion | Auto-play animations |
| Minimum 44x44px touch targets | Make tiny interactive elements |
| 4.5:1 contrast ratio for text | Use low-contrast text |