AI en WCAG: is jouw webshop vandaag nog écht toegankelijk?

AI en WCAG: is jouw webshop vandaag nog écht toegankelijk?

Veel teams weten wát de WCAG-richtlijnen zeggen, maar falen in de praktijk bij de implementatie: onjuiste ARIA, ontbrekende labels, keyboard traps en modals die niet toegankelijk zijn maken een site onbruikbaar voor echte gebruikers. Dit artikel richt zich op directe, testbare oplossingen die developers, frontend engineers, UX/UI designers en content-editors meteen kunnen toepassen.

Wij laten zien hoe je fouten voorkomt met concrete codevoorbeelden, checklisten en testinstructies. Wil je direct weten hoe toegankelijk jouw site is? Test je site met onze WCAG checker/validator, download onze plugin via de pluginpagina of neem contact op via ons contactformulier (vragen worden binnen 24 uur beantwoord).

Het probleem in de praktijk

Veelvoorkomende fouten

  • Visuele elementen die niet semantisch zijn (divs als knoppen zonder role/keyboard handlers).
  • Formuliervelden zonder gekoppelde <label>, of labels die visueel verborgen zijn maar niet toegankelijk voor screenreaders.
  • Onjuiste of overmatig gebruik van ARIA waardoor native semantics worden verbroken.
  • Modal dialogs zonder focus trapping en zonder aria-modal / aria-hidden beheer.
  • Ontbrekende alt-teksten, onduidelijke linkteksten en slechte kopstructuur (<h1>… volgorde).
  • Contrastproblemen en tekst die niet schaalbaar is.

Waarom dit vaak gebeurt

Time-to-market, componentisatie en UI-libraries dwingen ontwikkelaars soms tot workarounds. Designers leveren visuele specs zonder toegankelijke varianten; content-editors plaatsen afbeeldingen zonder alt en gebruiken “lees meer” als linktekst. Wij helpen teams dit structureel op te lossen met patterns, component-implementaties en testbare workflows.

Zo los je dit op in code

1) Knoppen en interactieve elementen: gebruik native elementen

Stap 1: Gebruik <button> voor klikbare acties. Stap 2: Voor link-achtige acties gebruik <a href=”…”>. Gebruik aria alleen als je semantics niet kunt bereiken met native elementen.

<!-- Correct: native button --><br><button type="button" class="primary">Bestel nu</button>

2) Formulieren: labels en foutmeldingen

Altijd een expliciet label koppelen; gebruik aria-describedby voor foutmelding en geef foutstatus aan met aria-invalid.

<label for="email">E-mailadres</label><br><input id="email" name="email" type="email" aria-describedby="email-help email-error"><br><small id="email-help">We sturen je een bevestiging</small><br><div id="email-error" role="alert" aria-live="assertive" style="display:none;color:#b00020">Voer een geldig e-mailadres in</div>

3) Modals: focus trapping en aria-hidden

Implementatie-stappen: 1) Markeer modal met role=”dialog” en aria-modal=”true”. 2) Zet rest van de app aria-hidden=”true” tijdens open. 3) Trap focus binnen modal. 4) Maak Esc-toets en close-knop beschikbaar.

<!-- Modal basis --><br><div id="dialog" role="dialog" aria-modal="true" aria-labelledby="dialog-title" tabindex="-1"><br><h2 id="dialog-title">Winkelwagen</h2><br><button id="close">Sluiten</button><br></div><br><script>// Focus trap (basis)const dialog = document.getElementById('dialog');const close = document.getElementById('close');function openDialog(){document.getElementById('app').setAttribute('aria-hidden','true');dialog.style.display='block';dialog.focus();}function closeDialog(){document.getElementById('app').removeAttribute('aria-hidden');dialog.style.display='none';close.blur();}close.addEventListener('click',closeDialog);document.addEventListener('keydown',e => { if(e.key === 'Escape') closeDialog(); });</script>

4) Keyboard access: tabindex en focus-visible

Geef alleen tabindex=”0″ aan elementen die normaal niet focusbaar moeten zijn en gebruik :focus-visible voor visuele focus.

<!-- Maak div focusbaar alleen als nodig --><br><div role="button" tabindex="0" aria-pressed="false">Meer opties</div><br><style>:focus-visible{outline:3px solid #005fcc;}</style>

5) Afbeeldingen en alt-teksten

Regel: beschrijf functionele afbeeldingen, laat decoratieve afbeeldingen leeg alt=”” of gebruik CSS background-image voor purely decorative items.

<!-- Functioneel --><br><img src="/product.jpg" alt="Rode wandelschoenen maat 42"><br><!-- Decoratief --><br><img src="/decor.png" alt="" role="presentation">

6) Live updates: aria-live en role=”status”

Gebruik aria-live voor dynamische content zoals winkelwagen tellingen of foutmeldingen. Gebruik role=”status” voor niet-kritieke updates en role=”alert” voor kritieke fouten.

<div aria-live="polite" id="cart-count">0</div><br><script>function setCartCount(n){document.getElementById('cart-count').textContent = n;}</script>

7) Contrast en schaalbaarheid

Check contrast ratio minimaal 4.5:1 voor body-tekst en 3:1 voor grote tekst. Gebruik rems voor font-size en vermijd fixed pixels voor UI-schaalbaarheid.

html{font-size:16px;}body{font-size:1rem;}/* Gebruik kleuren met voldoende contrast */

Checklist voor developers

  • Gebruik native elementen (button/a/form) waar mogelijk.
  • Alle inputs hebben <label for=”…> of aria-label/aria-labelledby.
  • Modals: role=”dialog”, aria-modal=”true”, focus trap en terugzetten van focus bij sluiten.
  • Geen tabindex>0 massaal inzetten; beperk focusable elements tot wat functioneel is.
  • Gebruik aria-live voor dynamische content, role=”alert” voor fouten.
  • Alt-teksten: functioneel beschrijven, decoratief leeg alt=”” met role=”presentation”.
  • Contrast-check met ratios en font-sizes in rems.
  • Automatiseer regressie: integreer axe-core in CI of gebruik onze plugin voor snelle scans.

Tips voor designers en redacties

Design tokens en component library

Leg kleur- en typografietokens vast met toegankelijke waarden. Voorbeeld: primary-color moet een contrast-check passeren i.c.m. white/black. Documenteer welke component states focus-visible moeten tonen.

Kopstructuur en contentrichtlijnen voor redacties

Gebruik logische headinghiërarchie (1 per pagina). Schrijf linkteksten die zelfstandig betekenis hebben (vervang “lees meer” door “Productdetails wandelschoenen”). Voeg alt-teksten toe bij upload en maak alt verplicht in CMS indien afbeelding functioneel is.

Design handoffs

Lever states (focus, hover, disabled) mee in Figma/Sketch en exporteer accessible tokens. Test prototypes met keyboard-only navigatie en spreek ontwikkelaars aan op ontbrekende semantics.

Hoe test je dit?

Automatisch

Start altijd met een automatische scan: onze WCAG checker/validator geeft snelle inzichten en concrete foutlocaties. Integreer axe-core lokaal of in CI:

// npm i -D axe-core puppeteer<br>const puppeteer = require('puppeteer');const {configureAxe, runAxe} = require('axe-puppeteer');(async ()=>{const browser = await puppeteer.launch();const page = await browser.newPage();await page.goto('https://jouwdomein.nl');const results = await new (require('axe-core'))().run();console.log(results);await browser.close();})();

Handmatig

1) Keyboard-only: tab door de pagina, activeer alle controls, test modals, dropdowns en forms. 2) Screenreader: NVDA (Windows) of VoiceOver (macOS). 3) Contrast: gebruik de color-contrast tool of onze checker.

Concrete testscript (5 minuten)

  1. Open pagina, druk Tab 10x: kun je alle interactieve items bereiken? Noteer misses.
  2. Open winkelwagen modal: focus moet in modal blijven; Esc sluit modal.
  3. Voeg product toe: wordt aria-live update voor cart-count aangekondigd?
  4. Bekijk productafbeeldingen: hebben ze correcte alt-teksten?
  5. Controleer contrast op producttitel en buttons met onze checker.

Loop na elke test de items af en fix de code direct. Test opnieuw met onze WCAG checker/validator of met onze plugin.

Extra implementatie voorbeelden

ARIA pattern: toggle switch

<!-- Schakel met juiste ARIA --><br><button role="switch" aria-checked="false" id="promo-switch">Promoties uit</button><br><script>const sw = document.getElementById('promo-switch');sw.addEventListener('click',()=>{const checked = sw.getAttribute('aria-checked') === 'true';sw.setAttribute('aria-checked', String(!checked));sw.textContent = !checked ? 'Promoties aan' : 'Promoties uit';});</script>

ARIA live voor foutmeldingen (form submission)

<form id="checkout"><br><input id="zip" name="zip"><br><div id="form-status" aria-live="assertive" role="status"></div><br></form><br><script>document.getElementById('checkout').addEventListener('submit',e => {e.preventDefault();const zip = document.getElementById('zip').value;if(!/^\d{4}\s?[A-Z]{2}$/.test(zip)){document.getElementById('form-status').textContent = 'Controleer je postcode';return;}document.getElementById('form-status').textContent = 'Bestelling verwerkt';});</script>

Actie: waar te beginnen

1) Draai direct een scan met onze checker/validator en fix de top 10 issues. 2) Installeer onze plugin voor je browser of CI. 3) Heb je een specifiek probleem? Vul het contactformulier — wij reageren binnen 24 uur en helpen met concrete codechanges.

Laatste praktische tip: voeg dit kleine script op je ontwikkelomgeving toe om snel keyboard traps te vinden — het highlight alle focusbare elementen en logt wanneer focus buiten de pagina verdwijnt:

// Focus-audit snippet (dev only)<br>(function(){const focusables = 'a,button,input,select,textarea,[tabindex]';const els = Array.from(document.querySelectorAll(focusables)).filter(e => e.tabIndex >= 0);els.forEach(e => e.style.outline = '1px dashed rgba(255,0,0,0.5)');window.addEventListener('focusout',e => {setTimeout(()=>{if(document.activeElement === document.body){console.warn('Mogelijke keyboard trap: focus is terug op body', e.target);}},10);});console.info('Focus audit active — verwijder in productie');})();
Previous Post Next Post

Geef een reactie

Je e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *