Accessibility
Alt text, labels, keyboard and ARIA — only as much as needed.
Updated
What accessibility is
Accessibility (a11y — "a", 11 letters, "y") means the site can be used by anyone:
- with the keyboard (no mouse — many power users and people with motor disabilities);
- with a screen reader (a program reads the page out loud — blind users);
- with zoom or low vision;
- with color blindness, on a screen in the sun, with one hand busy.
Since 2025 it's also a legal requirement in the EU for many sites (the European Accessibility Act). Bonus: what's accessible is easier to test automatically and better indexed.
How a screen reader "sees" the page
It doesn't see pixels — it reads the accessibility tree, built from the HTML. For every element it knows:
| Property | Example | Where it comes from |
|---|---|---|
| role | button, link, heading, list | the tag (<button>) or role |
| name | "Close" | the text, alt, <label>, aria-label |
| state | pressed, expanded, disabled | disabled, aria-expanded, aria-pressed |
That's why semantic HTML is 80% of accessibility: <button>Save</button> already has a role and a name, and it's focusable.
The 6 rules that cover most cases
- Semantic HTML —
button,a,nav,main,label. - Alternative text —
<img alt="Description">; a decorative image →alt=""(empty, not missing — otherwise the file name gets read). - Every input has a label —
<label for>or, if there's no visual space,aria-label. - Everything works from the keyboard — Tab reaches everything in a logical order; focus is visible (
:focus-visible). - Contrast — at least 4.5:1 for normal text, 3:1 for large text (WCAG AA).
- Icon buttons have a name —
<button aria-label="Close">✕</button>.
ARIA — only when HTML isn't enough
ARIA = attributes that add information for assistive technologies. The first rule of ARIA: don't use ARIA if a native element exists.
<!-- ✗ you have to add role, tabindex, a handler for Enter and Space... -->
<div role="button" tabindex="0" onclick="save()">Save</div>
<!-- ✓ all of it for free -->
<button type="button">Save</button>Kinds of ARIA attributes:
| Kind | Attributes | Example use |
|---|---|---|
| name / description | aria-label, aria-labelledby, aria-describedby |
an icon button, an error message linked to an input |
| state | aria-expanded, aria-pressed, aria-current, aria-invalid |
an open menu, a toggle, the current page, a wrong field |
| live regions | aria-live="polite" |
toasts, errors that appear after submit |
| hiding | aria-hidden="true" |
a decorative icon next to text |
Link or button?
<a href> |
<button> |
|
|---|---|---|
| What it does | takes you somewhere (changes the URL) | does something (submit, open, delete) |
| Keyboard | Enter | Enter and Space |
| Right click → new tab | yes | no |
How to test in 5 minutes
- Use the page only with Tab / Shift+Tab / Enter / Space / Esc.
- Chrome DevTools → Lighthouse → Accessibility.
- Zoom to 200% — the layout must not break.
- macOS: VoiceOver (Cmd+F5) for 2 minutes — eye-opening.
Summary
- A screen reader reads role + name + state, from the HTML.
- Semantic HTML solves most problems; ARIA only fills the gaps.
- Keyboard, visible focus, contrast,
alt,label.