Web accessibility is no longer optional: since June 28, 2025, the European Accessibility Act makes it mandatory for most private-sector digital services. Here's a practical guide for developers: the WCAG principles, the most common mistakes, and how to fix them with real code.
Why accessibility, and why now
Making a site accessible means letting a blind, low-vision, deaf, motor-impaired or cognitively impaired person use the service like everyone else. That's roughly 20% of the population, and beyond permanent disability, everyone benefits from an accessible site: keyboard navigation, readable contrast in bright sunlight, captions on the train.
The context changed in 2025. The European Accessibility Act (directive 2019/882) has applied since June 28, 2025 to many private-sector digital services: e-commerce, banking, transport, online services. In France, the RGAA (Référentiel Général d'Amélioration de l'Accessibilité) remains the official framework for the public sector and some companies. Both rest on the same technical foundation: the WCAG.
Takeaway: accessibility is no longer just a matter of ethics or image. It's a legal obligation, with a risk of penalty, and it also improves SEO and conversion. Better to handle it from day one.
WCAG: the 4 principles and the 3 levels
The Web Content Accessibility Guidelines (version 2.2, the most recent) rest on 4 principles, summed up by the acronym POUR: Perceivable, Operable, Understandable, Robust. Each criterion is graded across three conformance levels.
| Level | Requirement | Legal target |
|---|---|---|
| A | Bare minimum | Not enough alone |
| AA | Expected standard | Yes (EAA, RGAA) |
| AAA | Enhanced | Optional, case by case |
The level required by law is AA. That's the one that should guide your daily choices.
The 6 most common mistakes (and their fixes)
1. Non-semantic HTML (the do-everything div)
The most widespread mistake: a <div onclick> instead of a real button. The screen reader doesn't announce it as clickable, and it isn't keyboard-focusable. The fix is free: use the right element.
<!-- Avoid: invisible to keyboard and screen reader -->
<div class="btn" onclick="submit()">Send</div>
<!-- Correct: focusable, keyboard-activatable, announced as a button -->
<button type="submit">Send</button>
2. Images without a text alternative
Every meaningful image needs an alt attribute describing its content. A purely decorative image takes an empty alt so the screen reader skips it.
<img src="sales-chart.png"
alt="Sales up 30% between January and March">
<!-- Decorative image: empty alt, never a missing alt -->
<img src="divider.svg" alt="">
3. Insufficient contrast
Light grey on a white background looks nice in the mockup and is unreadable in real life. Level AA requires a contrast ratio of at least 4.5:1 for normal text, and 3:1 for large text (from 24px, or 18.5px bold).
| Text type | AA minimum ratio |
|---|---|
| Normal text | 4.5:1 |
| Large text | 3:1 |
| Components and icons | 3:1 |
4. Broken keyboard navigation
A user who can't use a mouse must be able to do everything with the Tab key. Two rules: never remove the visible focus, and provide a skip link to jump straight to the content.
/* NEVER remove the outline without replacing it */
:focus-visible {
outline: 2px solid var(--tb-accent);
outline-offset: 2px;
}
<!-- Skip link, the first focusable element on the page -->
<a href="#content" class="skip-link">Skip to content</a>
5. Forms without linked labels
A field without an associated <label> is a silent input for the screen reader. The link is made with for and id.
<label for="email">Email address</label>
<input id="email" type="email" name="email"
autocomplete="email" required>
6. Misused ARIA (worse than no ARIA)
ARIA exists to express what native HTML can't, not to replace it. ARIA's first rule: if a native HTML element exists, use it. A wrong role breaks more than it fixes. Reserve ARIA for rich components (tabs, modals, menus) and dynamic content.
<!-- Announce a dynamic message without moving focus -->
<div aria-live="polite" id="status"></div>
How to test your accessibility
No automated tool covers everything. The right approach combines automated and manual checks.
- By keyboard: unplug the mouse and go through the whole site with Tab. If you can, you've already solved half the problems.
- With a screen reader: test with VoiceOver (macOS/iOS), NVDA (Windows) or TalkBack (Android).
- Automated: axe DevTools, Lighthouse or Pa11y catch mechanical errors (contrast, missing alt, labels).
- Contrast: Chrome DevTools' contrast panel or a dedicated tool.
Takeaway: automated tools catch roughly 30% to 40% of issues. The rest surfaces with the keyboard and the screen reader. A serious audit always does both.
The baseline accessibility checklist
- Semantic HTML (buttons, links, hierarchical
h1-h6headings) - Relevant
alton every meaningful image - AA contrast verified (4.5:1 for normal text)
- Full keyboard navigation, visible focus preserved
- Skip link to the main content
- Linked labels on every form field
- Error messages and dynamic content announced (
aria-live) - Keyboard and screen-reader testing before going live
Going further
Accessibility is part of a site's overall quality, just like performance. See also my audit method: Web performance audit, my 5-step method.
Does your site need to comply with the European Accessibility Act? Let's talk.