Accessibility isn't a feature you ship — it's a property of every component you build. Four WCAG principles, one keyboard contract, semantic HTML first. Get this foundation right and every audit gets cheaper.
01 — POUR
WCAG 2.1 organizes itself around four principles: Perceivable, Operable, Understandable, Robust. If a component can be put under those four headings and ticked, it's accessible — independent of what the design looks like.
01
Content has to reach the user — text alternatives for images, captions for audio, contrast that survives glare. If a sense isn't available, another sense has to carry the same information.
02
Every action a mouse user can take, a keyboard user can take. No interaction depends on a single input modality, and no timing trap stops a user who needs longer.
03
Text is readable. Predictability is honored — same component, same behavior. Errors are described in plain language with a fix, not a code.
04
The markup parses cleanly so any assistive tech can interpret it. Use the right HTML element first; ARIA is a patch for what HTML can't express natively.
02 — Keyboard
The keyboard contract is the simplest accessibility test there is — unplug the mouse and try to use the product. If a flow fails, that flow is broken for everyone using switch access, voice control, or simply preferring the keyboard for speed.
Test
Open any page in your product. Press Tab repeatedly. Can you reach every interactive element? Is the focus order logical? Is the focus ring visible at every stop? That's 80% of the keyboard audit.
03 — Focus management
The focus ring tells keyboard users where they are. Removing it without a replacement breaks the product for anyone not using a mouse. Use :focus-visible so the ring shows for keyboard but not for mouse clicks — solving the most common objection to the default browser ring.
Avoid · invisible
outline: none with no replacement — invisible to keyboard users.
OK · browser default
The browser default works but reads as unfinished. Custom is better.
Prefer · branded
:focus-visible ring matching brand — visible, on-brand, off for mouse clicks.
Tab into each button to see how they behave. Use :focus-visible instead of :focus so the ring shows for keyboard but not mouse clicks.
04 — Semantic HTML
Native HTML elements carry accessibility for free — <button> is focusable, announced as a button, responds to Enter/Space, all without a single line of JavaScript. ARIA exists to describe patterns HTML can't express; if you find yourself adding role="button" to a div, use a button instead.
05 — Testing
Automated tools catch about a third of real accessibility issues — contrast, missing alt, invalid markup. The other two thirds are interaction patterns that need a human: focus order, screen-reader announcements, keyboard traps in modals. Both layers matter; neither replaces the other.
Automated · in CI
Manual · per release
06 — Anti-patterns
Real findings from real audits. Each one ships in week one, gets flagged in a quarterly review, and takes longer to retrofit than to do right the first time.
Avoid
<div onClick={...}>Save</div>Prefer
<button type="button" onClick={...}>Save</button>A div isn't focusable, isn't announced as interactive, doesn't respond to Enter/Space. Every clickable thing is a button or a link — no exceptions outside of grids that need composite roles.
Avoid
*:focus { outline: none }Prefer
Custom :focus-visible ring matching brandRemoving the ring removes navigation for everyone using a keyboard. Style the ring instead — make it match the brand, raise contrast, but never make it invisible.
Avoid
<input placeholder="Your email">Prefer
<label for="email">Email</label> <input id="email">Placeholder disappears on focus, fails contrast at 60% opacity, and isn't announced consistently by screen readers. Visible label + helper text covers every case.
Avoid
<button role="button" aria-pressed="false">Prefer
<button> · let HTML semantics do the workARIA duplicates what HTML already provides — and wrong ARIA is worse than none. Rule of ARIA: don't use ARIA. Reach for it only when HTML genuinely can't express the pattern.
Continue
Design principles are the shared agreement on what good looks like — the rules that decide arguments before the meeting starts. Read how to write principles that aren't just slogans.