WCAG in de praktijk: direct toepasbare oplossingen voor developers en redacties
Toegankelijkheid faalt vaak niet door onwil maar door onduidelijke implementatie: verkeerde ARIA, gebrek aan keyboard-focus, slechte form labels en kleurcontrasten die alleen tijdens ontwerpfase worden gecontroleerd. Dit artikel vertaalt WCAG-normen naar concrete stap-voor-stap code en testbare checks zodat ontwikkelaars, designers en redacties meteen kunnen handelen.
Wij bij wcagtool.nl specialiseren ons in praktische toepassing: voorbeelden die je direct in je codebase plakt, test-scripts die je uitvoert en tools (checker, plugin) die feedback geven. Test je site direct met onze WCAG checker/validator of download onze plugin vanaf de pluginpagina. Vragen? Gebruik ons contactformulier — wij antwoorden binnen 24 uur.
Het probleem in de praktijk
Veelvoorkomende fouten
Ontwikkelaars en redacties maken structurele fouten die tot falende toegankelijkheid leiden. De top 6:
- Semantiek ontbreekt: divs in plaats van buttons/links.
- Keyboard interactions: elementen zijn niet bereikbaar of misgedrag bij Enter/Space.
- Focusmanagement: geen zichtbare focus, focus verdwijnt na modals/dynamische updates.
- ARIA-misbruik: eigenschappen toegepast zonder semantische ondersteuning.
- Forms zonder labels of verkeerde foutmeldingen.
- Kleurcontrast en afbeeldingen zonder alt-tekst.
Waarom dat lastig blijft
Designers leveren kleuren en componenten, developers implementeren snel, redacties vullen content. Zonder concrete handvatten en test-scripts ontstaan inconsistenties. Wij lossen dit op door code-standaarden, checklists en CI-tests die je direct aan je workflow koppelt.
Zo los je dit op in code
1. Gebruik altijd semantische HTML
Stap-voor-stap:
- Vervang clickable <div> voor <button> of <a> met href.
- Als visueel een link moet lijken: gebruik <a href=”#” role=”button”> alleen wanneer het echt navigatie is; anders <button>.
Voorbeeld: correcte knop
<button type="button" class="btn-primary" aria-pressed="false">Voeg toe</button>
2. Keyboard- en click-compatibiliteit
Regel: native elementen halen keyboard-compatibiliteit al binnen. Gebruik de volgende patronen als je custom elementen bouwt.
<!-- Custom 'button'-achtige div: voeg roles en keyboard handlers toe --><div role="button" tabindex="0" aria-pressed="false" class="custom-btn" onclick="handleClick()" onkeydown="if(event.key==='Enter'||event.key===' ') { event.preventDefault(); handleClick(); }">Actie</div>
3. Focus management en zichtbare focus
CSS focus-styling moet altijd aanwezig zijn en niet uitgezet door resetstyles. Voeg focus-visible toe:
/* Gebruik focus-visible voor browsers die het ondersteunen */.custom-btn:focus{outline:2px solid #005fcc;outline-offset:2px;}@media (prefers-reduced-motion: no-preference){:focus{transition:box-shadow .12s;}}
Wanneer je modals of overlays opent: trap de focus en zet focus terug bij sluiten. Voorbeeld met JavaScript:
// Eenvoudige focus trap (niet productieklaar zonder extra checks)const firstFocusable = modal.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');const focusable = Array.from(modal.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'));const lastFocusable = focusable[focusable.length-1];modal.addEventListener('keydown', (e)=>{ if(e.key==='Tab'){ if(e.shiftKey && document.activeElement===firstFocusable){ e.preventDefault(); lastFocusable.focus(); } else if(!e.shiftKey && document.activeElement===lastFocusable){ e.preventDefault(); firstFocusable.focus(); } } });
4. ARIA correct toepassen
Regel: voeg ARIA alleen toe als native HTML niet volstaat. Gebruik role, aria-labelledby, aria-describedby en aria-live correct.
<!-- Voorbeeld: dynamische foutmelding bij formulier --><div id="error-summary" role="alert" aria-live="assertive">Er is een fout bij het invullen van uw e-mailadres</div>
5. Toegankelijke formulieren
Stap-voor-stap:
- Gebruik <label for="id"> gekoppeld aan input met matching id.
- Gebruik aria-describedby voor extra instructies.
- Toon foutboodschappen inline en in een samenvatting met role=”alert”.
<label for="email">E-mail</label><input id="email" name="email" type="email" aria-describedby="emailHelp error-email" required /><div id="emailHelp">We gebruiken dit om in te loggen</div><div id="error-email" role="alert" aria-live="polite"> </div>
6. Afbeeldingen en alt-teksten
Regels:
- Decoratieve afbeeldingen: <img alt=”” role=”presentation”>
- Informatieve afbeeldingen: beschrijf beknopt in alt.
- Complexe afbeeldingen: geef extra beschrijving naast of via aria-describedby met id naar langere beschrijving.
<img src="grafiek.png" alt="Omzet gestegen van 2019 naar 2024, piek in 2023" /><img src="decoratie.svg" alt="" role="presentation" />
7. Kleurcontrast direct in CSS afdwingen
Gebruik variabelen en controleer in design system. Voorbeelden:
:root{--brand:#005fcc;--text:#1b1b1b;--muted:#666}body{color:var(--text);background:#fff} .btn-primary{background:var(--brand);color:#fff} /* check contrast via tool: tekstkleur op achtergrond moet voldoen aan 4.5:1 voor normale tekst */
Checklist voor developers
Gebruik deze checklist tijdens code review en CI:
- Semantische tags gebruikt (header, nav, main, footer, button, form)?
- Alle interactieve elementen focusbaar met tabindex of native elementen?
- Visible focus-styles aanwezig en consistent?
- ARIA alleen als ondersteuning, geen vervanging van semantiek?
- Form labels gekoppeld en foutmeldingen met role=”alert”?
- Afbeeldingen correct alt-tekst of alt=”” voor decoratie?
- Kleurcontrast minimaal 4.5:1 voor bodytekst, 3:1 voor grote tekst?
- Toegankelijkheidschecks in CI met axe-core of onze plugin?
Voor automatische checks in je pipeline: voorbeeld Node script met axe-core
const { AxePuppeteer } = require('axe-puppeteer');const puppeteer = require('puppeteer');(async ()=>{const browser = await puppeteer.launch();const page = await browser.newPage();await page.goto('https://your-site.example');const results = await new AxePuppeteer(page).analyze();console.log(JSON.stringify(results.violations, null, 2));await browser.close();})();
Of: test direct met onze online WCAG checker/validator en voeg de plugin toe voor IDE/browser-integratie: Download plugin. Vragen? Gebruik ons contactformulier — antwoord binnen 24 uur.
Tips voor designers en redacties
Design tokens en kleurkeuze
Werk met design tokens (CSS-variabelen) en zorg dat elke kleurcombinatie automatisch door contrasttests gaat. Voorbeeld workflow:
- Definieer tokens in tokens.json of :root.
- Gebruik tooling die contrast berekent (CI) en continu checkt.
{ "colors": { "brand": "#005fcc", "text": "#1b1b1b", "muted":"#666" } }
Contentrichtlijnen voor redacties
Concrete regels:
- Headings: structureer content met H1-H6 in volgorde, nooit skippen.
- Alt-teksten: korte en begrijpelijke omschrijving; geen “afbeelding van …”.
- Links: duidelijke linktekst (geen “klik hier”).
- Formulieren: schrijf heldere fouten met actiegerichte instructie (“Voer een geldig e-mailadres in: example@domein.nl”).
UX-patterns die designers moeten leveren
Lever in component library: focus-states, disabled-states, error-states, aria-attributes voorschriften en voorbeelden met content. Voeg ook microcopy voor screenreaders toe.
Hoe test je dit?
Handmatige tests (snel en effectief)
1) Keyboard-only: verwijder muis en navigeer met Tab/Shift+Tab, Enter en Space. Verwacht: alle interactieve items bereikbaar en logisch volgorden.
2) Screenreader testen: gebruik NVDA (Windows) of VoiceOver (Mac). Check: headings, linkteksten, labels en bij interactieve elementen duidelijke aankondiging van status (aria-pressed, aria-expanded).
NVDA snelle stappen: open NVDA, navigeer met ‘H’ voor headings, ‘K’ voor links, en luister naar error/success announcements.
Automatische tools
Gebruik meerdere tools: axe-core, Lighthouse, en onze WCAG checker/validator. Combineer automatische en handmatige tests omdat tools niet alles detecteren (bv. inhoud van alt-teksten).
// Gebruik axe-core in browserconsole (snel)await axe.run(document).then(results => console.log(results.violations));
Testgevallen die je altijd moet doorlopen
- Form validation: onjuiste input tonen van foutmelding en geven van focus naar first error.
- Modal open/close: focus trap en terugplaatsen focus naar trigger.
- Dynamic content: updates via aria-live voor screenreaders.
- Contrast: check alle varianten (hover/active/disabled) met contrasttool.
Test direct je site met onze online checker of installeer de wcagtool plugin in je browser/devtools. Heb je vragen? Gebruik ons contactformulier — antwoord binnen 24 uur.
Extra code-snippets & praktische how-to’s
Skip link implementatie
Voeg een skip link toe voor snelle navigatie:
<a class="skip-link" href="#main-content">Sla navigatie over</a><!-- CSS -->.skip-link{position:absolute;left:-999px;top:auto;width:1px;height:1px;overflow:hidden} .skip-link:focus{position:static;left:0;width:auto;height:auto;padding:8px;background:#000;color:#fff;z-index:1000}
ARIA-live voor dynamische updates
Gebruik aria-live region voor feedback na acties:
<div id="toast" aria-live="polite" aria-atomic="true"></div>function showToast(msg){const toast = document.getElementById('toast');toast.textContent = msg;}
Formulier valideren met focus naar fout
function validate(form){const firstInvalid = form.querySelector(':invalid');if(firstInvalid){firstInvalid.focus();const err = document.getElementById('error-'+firstInvalid.id); if(err){err.textContent = firstInvalid.validationMessage;}}}
Actiegerichte implementatie in 5 minuten
- Voer onze WCAG checker uit op je homepage en noteer top 3 violations.
- Voeg skip link toe en test keyboard-navigatie (2 minuten).
- Kijk naar eerste formulier, voeg ontbrekende <label> toe en role=”alert” voor fouten (5-10 minuten).
- Controleer contrast van primaire tekst en knoppen met onze checker (3 minuten).
- Installeer de plugin voor snelle lokale checks in je browser.
Blijf niet hangen in perfectie: repareer de grootste problemen eerst en draai daarna regressietests in CI.
Checklist voor QA en deployment
- Automatische accessibility-scan in CI (axe/puppeteer script).
- Principe “no tabindex > 0” zonder expliciete reden.
- Documenteer ARIA-usage in component library.
- Redactiegids: alt-teksten, linkteksten, headings checklist.
- Regelmatige audits met wcagtool.nl checker.
Wil je dat wij meekijken? Upload je URL naar onze WCAG checker/validator of vraag een audit via het contactformulier. Antwoord binnen 24 uur.
Laatste praktische tip voor direct gebruik: plak deze korte focus-trap en test met Tab/Shift+Tab — vervang modal met jouw selector.
// Plak en test directconst modal = document.querySelector('#mijn-modal');const focusable = Array.from(modal.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'));const first = focusable[0];const last = focusable[focusable.length-1];modal.addEventListener('keydown', e => { if(e.key==='Tab'){ if(e.shiftKey && document.activeElement===first){ e.preventDefault(); last.focus(); } else if(!e.shiftKey && document.activeElement===last){ e.preventDefault(); first.focus(); } } });