Building accessible components
Four habits that remove most accessibility defects before they reach a reviewer, with the reasons behind each one.
Most accessibility defects are not hard problems. They are small habits that were missed early and then copied through a codebase. These four habits catch the majority of them.
Start from the native element
A button element is focusable, it responds to the keyboard, and screen
readers announce it correctly. A div with a click handler does none of that
until you add it back by hand. Start from the element that already behaves the
way you need, then style it.
The same rule applies to links. If the control moves the reader to another page, it is a link. If it changes something on the current page, it is a button.
Give focus a visible outline
Keyboard users need to see where they are. The theme on this site defines one
focus style and applies it with :focus-visible, so the outline appears for
keyboard users and stays out of the way for pointer users.
:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 3px;
}
Never remove an outline without adding a replacement that has the same contrast.
Name every control
A control needs a name that a screen reader can announce. Visible text is the
best name. When a control shows only an icon, add an aria-label, and make the
label describe the action, not the picture.
The theme toggle in the site header is labelled “Switch between light and dark theme”, not “Moon icon”.
Check colour contrast at both ends
This site ships a light theme and a dark theme. A colour pair that passes in one theme can fail in the other. Check body text, muted text, and link text in both, and keep the ratio at 4.5 to 1 or better for normal text.
A short review list
- Can you reach every control with the Tab key?
- Can you see where the focus is at all times?
- Does every image carry alt text, or an empty alt attribute when it is decorative?
- Does the page still make sense with styles turned off?
Run this list before asking for a review. It takes two minutes and it removes most of the comments a reviewer would otherwise write.