Home
Blog
Top 10 EAA-overtredingen op Europese websites — en hoe u ze op een middag oplost

Blog

Best Practices

Top 10 EAA-overtredingen op Europese websites — en hoe u ze op een middag oplost

Tien WCAG 2.1 AA-fouten die op de meeste EU-websites voorkomen, met kant-en-klare oplossingen. Los deze op en u dekt het grootste deel van automatisch detecteerbare EAA-bevindingen af.

Updated 15 May 2026

14 min read

Also in:

ENDE
NL
FR

Hoe we ze hebben gerangschikt

De volgorde is gebaseerd op prevalentie × juridisch risico, niet op pure frequentie. Een overtreding die overal voorkomt maar zelden wordt aangehaald (bijv. kleine kopregel-sprongen) scoort lager dan iets minder gangbaars dat regelmatig in klachten opduikt (bijv. niet-gelabelde formuliervelden op een betaalpagina).

Voor elk punt krijgt u:

  • Het WCAG 2.1 AA-criterium dat het schendt
  • De axe-core-regel die het detecteert
  • Waarom het u een klacht oplevert
  • De oplossing, met code

Laten we beginnen.

1. Ontbrekende alt-tekst op betekenisvolle afbeeldingen

WCAG: 1.1.1 Niet-tekstuele content (Niveau A) · axe-regel: image-alt

Dit is de meest aangehaalde bevinding in WCAG-audits en de eenvoudigste om op te lossen.

De fout die bijna iedereen maakt: het weglaten van alt op een decoratieve afbeelding, en vervolgens ook weglaten op een betekenisvolle afbeelding. Schermlezers kondigen dan niets aan voor de betekenisvolle afbeelding — en de gebruiker weet niet dat er een productfoto, een grafiek of een CAPTCHA is.

<!-- ❌ Slecht: betekenisvolle afbeelding zonder alt -->
<img src="/products/red-chair.jpg">

<!-- ✅ Goed: betekenisvolle afbeelding, beschrijvende alt -->
<img src="/products/red-chair.jpg" alt="Rode lederen fauteuil, mid-century stijl, zijaanzicht">

<!-- ✅ Goed: decoratieve afbeelding, lege alt is correct -->
<img src="/decorative/swoosh.png" alt="">

Belangrijke nuance: alt="" is het juiste antwoord voor echt decoratieve afbeeldingen. Het is niet het juiste antwoord voor "ik weet niet wat ik moet schrijven." Een ontbrekende beschrijving op een productafbeelding levert u een klacht op; een lege alt op een decoratief element is de spec-correcte keuze.

2. Onvoldoende tekst-achtergrondcontrast

WCAG: 1.4.3 Contrast (Minimum) (Niveau AA) · axe-regel: color-contrast

U heeft een contrastverhouding van minimaal 4,5:1 nodig voor normale tekst en 3:1 voor grote tekst (≥18pt of ≥14pt vet). Dit is de meest voorkomende AA-fout op landingspagina's — lichtgrijze tekst op witte achtergronden, merkgekleurde knoppen die de contrastvereiste niet halen.

Snel controleren: plak uw voorgrond/achtergrond hex in de WebAIM contrastchecker of de devtools van uw browser (Inspecteren → Toegankelijkheid-tabblad in Chrome/Firefox).

/* ❌ Slecht: verhouding 2,6:1, slaagt niet voor AA */
.muted { color: #aaaaaa; background: #ffffff; }

/* ✅ Goed: verhouding 4,6:1, slaagt voor AA */
.muted { color: #767676; background: #ffffff; }

/* ✅ Goed voor placeholders en uitgeschakelde states (nog steeds leesbaar) */
.disabled { color: #595959; background: #ffffff; } /* 7:1 */

Tegendraadse opmerking: veel designsystemen (Material, Apple HIG, Tailwind-standaardinstellingen) leveren gray-300 en gray-400 als veelgebruikte tekstkleuren op wit. Beide slagen niet voor AA. Auditeer uw design tokens eenmalig, niet uw pagina's.

3. Formuliervelden zonder programmatische labels

WCAG: 1.3.1 Informatie en relaties (Niveau A), 4.1.2 Naam, rol, waarde (Niveau A) · axe-regel: label

Dit is de hoogste-juridisch-risico-overtreding op e-commercesites. Een afrekenformulier waarbij schermlezers "E-mail", "Postcode", "CVV" niet kunnen aankondigen — dat is het soort fout dat handhavingsacties uitlokt.

<!-- ❌ Slecht: visuele placeholder, geen label -->
<input type="email" placeholder="E-mailadres">

<!-- ❌ Slecht: label niet gekoppeld -->
<label>E-mail</label>
<input type="email">

<!-- ✅ Goed: expliciete labelkoppeling -->
<label for="email">E-mail</label>
<input id="email" type="email">

<!-- ✅ Goed: aria-label wanneer visueel label niet praktisch is (bijv. alleen icoon) -->
<input type="search" aria-label="Producten zoeken">

<!-- ✅ Goed: aria-labelledby die verwijst naar bestaande zichtbare tekst -->
<span id="zip-label">Postcode</span>
<input aria-labelledby="zip-label">

placeholder is nooit een vervanging voor een label. Het verdwijnt zodra de gebruiker begint te typen.

4. Ontbrekende "sla over naar inhoud"-link

WCAG: 2.4.1 Blokken omzeilen (Niveau A) · axe-regel: skip-link

Gebruikers die alleen het toetsenbord of schermlezers gebruiken, moeten door elke navigatielink bladeren voordat ze de hoofdinhoud bereiken — op elke pagina. Een sla-over-link laat ze dit overslaan.

<!-- Plaats dit als het allereerste focusbare element in <body> -->
<a href="#main" class="skip-link">Sla over naar hoofdinhoud</a>
<!-- ... -->
<main id="main">...</main>
/* Visueel verbergen tot gefocust — gebruik nooit display:none */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
}
.skip-link:focus {
  left: 0;
  background: #000;
  color: #fff;
  padding: 0.75rem 1rem;
  z-index: 9999;
}

Als u Next.js / Nuxt / SvelteKit gebruikt, is dit één component die u importeert in uw root-layout. Vijf minuten om een van de meest gemelde overtredingen op te lossen.

5. Lege links en knoppen

WCAG: 2.4.4 Linkdoel (Niveau A), 4.1.2 Naam, rol, waarde (Niveau A) · axe-regels: link-name, button-name

Knoppen en links met alleen een icoon — het hamburgermenu, het zoekicoon, de sluit-X op modals — worden vaak geleverd zonder toegankelijke naam. Schermlezers kondigen "knop" aan zonder aanwijzing over wat het doet.

<!-- ❌ Slecht: icoknop, geen naam -->
<button><svg>...</svg></button>

<!-- ✅ Goed: aria-label geeft de naam -->
<button aria-label="Navigatiemenu openen">
  <svg aria-hidden="true">...</svg>
</button>

<!-- ✅ Goed: visueel verborgen tekst voor schermlezers -->
<button>
  <svg aria-hidden="true">...</svg>
  <span class="sr-only">Navigatiemenu openen</span>
</button>

aria-hidden="true" op de SVG is belangrijk — zonder dit kan de schermlezer zowel de SVG (vaak als "afbeelding") als het label aankondigen, wat storend is.

6. Ontbrekend taalattribuut op <html>

WCAG: 3.1.1 Taal van de pagina (Niveau A) · axe-regel: html-has-lang

Zonder lang weten schermlezers niet welke uitspraakregels ze moeten gebruiken — Nederlandse inhoud wordt met Engelse fonetiek voorgelezen, Duits in het Frans, en het resultaat is onverstaanbaar.

<!-- ❌ Slecht -->
<html>

<!-- ✅ Goed -->
<html lang="nl">

<!-- ✅ Goed voor meertalige inhoud met een primaire taal -->
<html lang="nl">
  <body>
    <p>De Engelse term <span lang="en">"deadline"</span> wordt veel gebruikt.</p>
  </body>
</html>

Dit is één attribuut. Er is geen excuus om het te missen.

7. Gebroken kopteksthiërarchie

WCAG: 1.3.1 Informatie en relaties (Niveau A) · axe-regel: heading-order

Schermlezers navigeren via kopteksten — "volgende koptekst" is een van de meest gebruikte opdrachten. Als uw pagina een h1 heeft en dan direct naar h4 springt, waarbij h2 en h3 worden overgeslagen, is de hiërarchie gebroken en mislukt de navigatie.

<!-- ❌ Slecht: h1 → h4 → h2 -->
<h1>Paginatitel</h1>
<h4>Subsectie</h4>
<h2>Andere sectie</h2>

<!-- ✅ Goed: monotoon, geen overgeslagen niveaus -->
<h1>Paginatitel</h1>
<h2>Sectie</h2>
<h3>Subsectie</h3>
<h2>Volgende sectie</h2>

Een veel voorkomende oorzaak is het gebruik van koptekstniveaus voor visuele opmaak. Doe dat niet. Gebruik het juiste niveau voor structuur, en stijl vervolgens met CSS.

8. Interactieve elementen die niet toegankelijk zijn via toetsenbord

WCAG: 2.1.1 Toetsenbord (Niveau A) · axe-regel: keyboard (handmatige + geautomatiseerde controles)

Elk klikbaar element moet bereikbaar en bedienbaar zijn via alleen het toetsenbord. De meest voorkomende fout: het gebruik van <div onclick=...> in plaats van <button>.

<!-- ❌ Slecht: niet focusbaar via toetsenbord, niet aangekondigd als knop -->
<div class="btn" onclick="doThing()">Klik hier</div>

<!-- ✅ Goed: native semantiek geeft toetsenbord + schermlezer gratis -->
<button type="button" onclick="doThing()">Klik hier</button>

<!-- ✅ Goed: als u absoluut een div moet gebruiken, voeg dit alles toe -->
<div
  role="button"
  tabindex="0"
  onclick="doThing()"
  onkeydown="if(event.key==='Enter'||event.key===' '){doThing()}"
>
  Klik hier
</div>

De derde optie is bijna altijd verkeerd. Gebruik een <button>. Het semantische element wint op elk criterium — toegankelijkheid, toetsenbord, focusstijlen, aankondiging door schermlezer, automatisch invullen door browser.

9. Modals zonder focusbeheer

WCAG: 2.4.3 Focusvolgorde (Niveau A), 2.1.2 Geen toetsenbordval (Niveau A) · gedeeltelijke automatisering, grotendeels handmatig

Een modal die focus niet vasthoudt is een frequente oorzaak van "ik opende de modal en kon er niet meer uit." Als een modal opent, moet focus erin worden verplaatst; terwijl hij open is, moet Tab binnen de modal cyclen; bij sluiting keert focus terug naar het triggerelement.

De juiste manier in 2026 is het native <dialog>-element:

<!-- ✅ Goed: native dialog met showModal() beheert focusval automatisch -->
<button type="button" onclick="document.getElementById('confirm-dialog').showModal()">
  Account verwijderen
</button>

<dialog id="confirm-dialog" aria-labelledby="dialog-title">
  <h2 id="dialog-title">Verwijdering bevestigen</h2>
  <p>Dit kan niet ongedaan worden gemaakt.</p>
  <form method="dialog">
    <button value="cancel">Annuleren</button>
    <button value="confirm">Verwijderen</button>
  </form>
</dialog>

Voor React/Vue/Svelte-componentbibliotheken, controleer of uw modal-component aria-modal, focusval en ESC-om-te-sluiten ondersteunt. De populaire (Radix UI, Headless UI, Mantine Modal, MUI Dialog) doen dat allemaal — maar aangepaste modals of oudere widgets van derden vaak niet.

10. Cookiebanners die alles blokkeren

WCAG: 2.1.1 Toetsenbord (Niveau A), 1.4.13 Inhoud bij aanwijzer of focus (Niveau AA), 4.1.2 · gedeeltelijke automatisering

Dit is de meest zichtbare fout voor gebruikers op Europese sites, omdat de AVG cookiebanners op elke site heeft opgelegd, en de meeste implementaties toegankelijkheidsrampen zijn:

  • Tabvolgorde houdt de gebruiker voor altijd gevangen in de banner
  • Knoppen zijn ongelabeld of gelabeld met vage tekst ("Alles accepteren" zonder context)
  • De banner overdekt de hoofdinhoud maar heeft niet de juiste rol / aria-modal
  • Schermlezers kunnen hem niet sluiten

De oplossing:

<!-- ✅ Goed: dialog-rol, toegankelijke naam, focusbeheer -->
<div role="dialog" aria-modal="true" aria-labelledby="cookie-title">
  <h2 id="cookie-title">Cookietoestemming</h2>
  <p>We gebruiken cookies voor analyses. U kunt alles accepteren, niet-essentiële weigeren of aanpassen.</p>
  <button>Alles accepteren</button>
  <button>Niet-essentiële weigeren</button>
  <button>Aanpassen</button>
</div>

Als u een CMP (Consent Management Platform) zoals Cookiebot, OneTrust of Iubenda gebruikt — controleer of ze WCAG doorstaan. De meeste grote platforms doen dit in hun standaardconfiguratie; veel zelfgebouwde banners niet.

Wat met de andere 30%?

De tien bovenstaande zijn detecteerbaar door geautomatiseerde tools. Ongeveer 30% van WCAG-fouten kan niet betrouwbaar worden geautomatiseerd:

  • Of alt="Foto van CEO" een betekenisvolle beschrijving is (versus alt="Anna Müller, CEO, glimlachend naar de camera")
  • Of kopteksten hun secties logisch beschrijven
  • Of de leesvolgorde zinvol is
  • Of inhoud begrijpelijk is in eenvoudige taal
  • Of formulieren correct herstellen bij fouten

Hiervoor is ofwel (1) een handmatige audit door een toegankelijkheidsspecialist nodig, ofwel minimaal een testpass met een echte schermlezer (NVDA op Windows is gratis en de standaard voor de meeste blinde gebruikers in Europa).

Voor de meeste MKB-bedrijven is de juiste aanpak: automatisering vangt het grootste deel op, dan een halve dag met een schermlezer om de kritieke gebruikersstromen te verifiëren (startpagina → product → afrekenen → account).

Over overlay-widgets, nogmaals, met overtuiging

Als uw projectmanager of baas zegt "laten we AccessiBe installeren", is hier het gesprek:

  • Ze herstellen de onderliggende HTML niet. Rechtszaken en klachten zijn gebaseerd op de broncode.
  • Ze breken regelmatig schermlezers die al zijn geconfigureerd op het apparaat van de gebruiker, omdat ze een concurrerend interactiemodel erbovenop leggen.
  • Ze worden niet erkend door EU-toezichthouders. De Franse handhavingsacties richtten zich specifiek op compliance op broncodeniveau.
  • De grootste overlay-leverancier schikte met de Amerikaanse FTC in 2024 voor misleidende claims over "WCAG-compliance met één regel JavaScript."

Er is geen overlay-snelkoppeling die een klacht overleeft. Los de broncode op.

Voor een diepgaande analyse van de juridische lagen, zie onze WCAG vs EN 301 549 vs EAA uitleg. Voor de per-land-boetes die deze klachten aandrijven, zie onze EAA-boetengids.

Hoeveel van deze overtredingen heeft uw site nu?

Webply voert een gratis WCAG 2.1 AA-scan uit op uw echte sjablonen, rangschikt problemen op EAA-juridisch risico en geeft u de ontwikkelaarsklare lijst met oplossingen. Geen creditcard. Geen overlay-widget.

Bronnen en verdere literatuur

  • W3C — WCAG 2.1 Beknopte referentie en ARIA Authoring Practices.
  • Deque Systems — axe-core regelsdocumentatie.
  • WebAIM Million 2024 / 2025 — jaarlijkse toegankelijkheidsanalyse van de top 1 miljoen startpagina's.
  • Europese Commissie — Richtlijn (EU) 2019/882 (EAA).
  • Franse handhavingsacties, november 2025 (Auchan, Carrefour, E.Leclerc, Picard) — behandeld in onze EAA-boetenoverzicht.

Codevoorbeelden zijn illustratief en minimalistisch — productiecode moet worden getest met echte ondersteunende technologie in uw specifieke framework. Geen juridisch advies.

WCAG 2.1 AA
Best Practices
DIY Oplossingen