Accessibility Rules
Semantics first
- Use the element that means what you mean. A
buttonfor an action, ana[href]for navigation,inputfor input. Every native element brings keyboard behavior, focus handling and a role for free. - Never put a click handler on a div or span. It is unreachable by keyboard and
invisible to assistive technology. If you catch yourself adding
tabindex,roleandonKeyDownto a div, you wanted a button. - ARIA is a last resort, not a garnish. The first rule of ARIA is not to use ARIA. A wrong role is worse than no role, because it overrides what was correct.
- Headings describe structure, not size. One
h1per page, no skipped levels. Use CSS for the size you want.
Names
- Every control needs an accessible name. A
labeltied to the input byfor, oraria-labelwhere no visible label exists. - Icon-only buttons need a name. An SVG is not a name. Add
aria-labeland mark the iconaria-hidden="true". - Link text must make sense alone. Screen reader users navigate by a list of links; "click here" and "read more" are useless in that list.
- Every meaningful image needs alt text describing its content. Every decorative
image needs
alt="", not a missing alt.
Keyboard
- Everything doable with a mouse must be doable with a keyboard. Tab to it, Enter or Space to activate it, Escape to dismiss it.
- Never remove the focus outline without replacing it.
outline: nonewith no replacement makes the page unusable for keyboard users. A visible, high-contrast focus style is not optional. - Tab order follows visual order. Do not reorder with positive
tabindex. Fix the DOM order instead. - Trap focus inside a modal while it is open, restore it to the trigger on close.
Visual
- Text contrast is at least 4.5:1, or 3:1 for large text. Check it, do not estimate it. Placeholder and disabled text are the usual failures.
- Never use color as the only signal. Pair it with text, an icon, or a pattern.
- The interface must work at 200% zoom and at 320px wide without horizontal scrolling.
- Respect
prefers-reduced-motion. Disable non-essential animation when it is set.
Dynamic content
- Announce important changes with a live region. A result that appears silently does not exist for a screen reader user.
- Move focus deliberately after a navigation or a modal opens, so the next Tab lands somewhere sensible.
- Form errors are associated with their field by
aria-describedby, and are text, not just a red border.