Toegankelijke formulieren en foutmeldingen: praktisch toepassen
Formulieren zijn essentieel, maar in de praktijk slagen veel teams er niet in om foutmeldingen en validatie toegankelijk te maken: onduidelijke labels, geen relatie tussen veld en foutmelding, geen focusmanagement en geen aankondiging voor schermlezers. Daardoor missen gebruikers fouten of raakt het proces onbruikbaar.
Wij van wcagtool.nl helpen je stap voor stap met concrete, testbare oplossingen: HTML-structuur, ARIA-attributen, eenvoudige CSS en JavaScript-snippets die je direct in je project kunt plakken. Test je site daarna meteen met onze WCAG checker, download onze plugin of vraag hulp via het contactformulier (antwoorden binnen 24 uur).
Het probleem in de praktijk
Symptomen die je vaak ziet
- Foutmeldingen zijn visueel, maar niet gekoppeld aan de invoervelden — schermlezers zien ze niet.
- Focus blijft op het formulier of springt niet naar het eerste foutveld, dit breekt keyboardgebruik.
- Inline validatie gebruikt alleen kleur (contrast-probleem, kleurblindheid).
- Toegankelijkheidsattributen worden misbruikt of ontbreken (bijv. incorrecte aria-describedby of role=”alert”).
Waarom dit vaak misgaat
Teams implementeren visuele validatie los van DOM-relaties of doen client-side scripting zonder te denken aan aria-live, focus or semantics. Automatische validators geven hints, maar leveren geen kant-en-klare implementatie voor gebruikersinteractie.
Zo los je dit op in code
1. Basis HTML-structuur: labels, ids en beschrijvingen
Gebruik altijd een <label> gekoppeld aan het <input> via het id. Voeg een element voor foutmeldingen toe met een unieke id en verwijs met aria-describedby.
<form id="signupForm" novalidate><div class="field"><label for="email">E-mail</label><input id="email" name="email" type="email" aria-describedby="emailHelp emailError" required /><div id="emailHelp" class="hint">We sturen een bevestiging naar deze e-mail.</div><div id="emailError" class="error" aria-live="polite" aria-atomic="true"> </div></div><button type="submit">Verstuur</button></form>
Uitleg
- novalidate op het formulier voorkomt browser-native UI die inconsistent kan zijn.
- aria-describedby bevat zowel hulptekst als foutmelding zodat screenreaders juiste context hebben.
- aria-live=”polite” zorgt dat schermlezers foutmeldingen aankondigen.
2. CSS: zichtbare staat, focus en kleuronafhankelijkheid
.error{color:#b00020;background:transparent;font-size:0.9rem}input[aria-invalid="true"]{outline:3px solid #ffcccb;box-shadow:0 0 0 3px rgba(176,0,32,0.08)}.visually-hidden{position:absolute!important;height:1px;width:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);border:0}
Uitleg
Zorg dat fouten niet alleen door kleur worden gecommuniceerd: gebruik ook iconen, tekst en outline. Gebruik .visually-hidden voor extra beschrijvingen voor schermlezers.
3. JavaScript: valideren, tonen van fouten en focusmanagement
Voeg een compacte validate-functie toe die fouten bijhoudt, aria-invalid zet, fouttekst injecteert en focus naar het eerste foutveld plaatst.
document.getElementById('signupForm').addEventListener('submit',function(e){e.preventDefault();const form=this;const errors=[];const email=form.querySelector('#email');if(!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.value)){errors.push({field:email,id:'emailError',message:'Voer een geldig e-mailadres in.'});}clearErrors(form);if(errors.length){showErrors(errors);errors[0].field.focus();errors[0].field.setAttribute('aria-invalid','true');}else{submitForm(form);}});function clearErrors(form){form.querySelectorAll('[aria-invalid]').forEach(el=>el.removeAttribute('aria-invalid'));form.querySelectorAll('.error').forEach(el=>el.innerHTML=' ');}function showErrors(errors){errors.forEach(err=>{const el=document.getElementById(err.id);if(el){el.innerText=err.message;}});}function submitForm(form){/* doe hier de ajax/post actie */console.log('Formulier klaar om te verzenden');}
Uitleg
- Set aria-invalid=”true” op foutieve velden.
- Zorg dat de foutcontainer een unieke id heeft en aria-live voor aankondiging.
- Plaats focus op het eerste foutveld — belangrijk voor keyboard-only gebruikers.
4. Inline validatie tijdens input (debug-safe)
email.addEventListener('input',function(){const errId='emailError';const errEl=document.getElementById(errId);if(this.value===''){this.removeAttribute('aria-invalid');errEl.innerHTML=' ';}else if(!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(this.value)){this.setAttribute('aria-invalid','true');errEl.innerText='E-mail is ongeldig.';}else{this.removeAttribute('aria-invalid');errEl.innerHTML=' '} });
Uitleg
Beperk frequent DOM-updates en voorkom dat aria-live te vaak wordt gefired — throttle indien nodig.
Checklist voor developers
- Labels: elk input heeft een <label for=”id”> of aria-label.
- Descriptive IDs: foutmeldingen hebben unieke ids en worden refererend via aria-describedby.
- aria-live of role=”alert” op foutcontainer voor aankondiging door schermlezers.
- aria-invalid op foutvelden zetten en verwijderen bij correctie.
- Focus management: focus naar eerste foutveld op submit.
- Geen afhankelijkheid op kleur alleen — voeg iconen/tekst en voldoende contrast toe.
- novalidate en eigen client-side validatie voor consistente ervaring.
- Progressieve enhancement: server-side validatie geeft dezelfde foutstructuur terug.
Tips voor designers en redacties
Ontwerpverloop voor foutmeldingen
- Plaats foutmelding visueel direct bij het veld; houd consistent spacing.
- Gebruik kort, concreet taalgebruik: “Vul je e-mail in” i.p.v. “Fout”.
- Gebruik iconen + tekst + kleur; test contrast met tools.
Contentrichtlijnen voor redacties
- Schrijf foutteksten die aangeven wat fout ging en hoe het op te lossen: “E-mailadres ongeldig — gebruik voorbeeld@domein.nl”.
- Houd tekst kort, activeer instructies en vermijd vakjargon.
Design-assets
Voorzie states: default, focus, invalid, valid. Maak componenten in design system met geanticipeerde aria- en id-velden zodat developers consistent kunnen implementeren.
Hoe test je dit?
Automatische checks
- Run axe-core of Pa11y in je CI — let op ontbrekende aria-describedby, aria-invalid gebruik en role=alert.
- Gebruik onze online WCAG checker: wcagtool.nl/checker — test live pagina’s of componenten en krijg direct prioritering en code-advies.
Handmatige tests
- Keyboard-only: navigeer naar form, laat velden leeg, druk op submit en controleer of focus naar eerst foutveld springt en fouttekst zichtbaar is.
- Screenreader: gebruik NVDA/VoiceOver, voer fout in en controleer of foutmelding wordt aangekondigd (aria-live/role alert).
- Colorblindness: schakel kleuren uit of gebruik grijswaarden en controleer dat fouten herkenbaar blijven.
- Contrast: meet met contrast-analyser bij fout- en focus-states.
Praktische testgevallen
- Leeg formulier versturen → focus naar eerste required veld + foutmelding.
- Ongeldig e-mailformaat → aria-invalid=true en foutmelding aangekondigd.
- Inline correctie → aria-invalid removed en foutmelding verdwijnt; schermlezer update.
Gebruik onze plugin
Installeer de wcagtool plugin voor Chrome/Firefox: Download plugin. Daarmee kun je direct foutcontainers inspecteren, aria-attributes simuleren en issues rapporteren.
Extra codevoorbeelden en patterns
Server-side foutreactie (JSON) — consistent met front-end
// Voorbeeld JSON response bij POST /signup 400 Bad Request{ "errors":[{"field":"email","message":"Voer een geldig e-mailadres in.","id":"emailError"}]}
Front-end integratie (fetch)
fetch('/signup',{method:'POST',body:new FormData(form)}).then(r=>r.json()).then(data=>{if(data.errors){clearErrors(form);const errors=data.errors.map(e=>({field:form.querySelector('[name=\"'+e.field+'\"]'),id:e.id,message:e.message}));showErrors(errors);errors[0].field.focus();}});
Checklist voor acceptatie (QA)
- Alle foutvelden hebben aria-describedby verwijzing naar fout-id.
- aria-live wordt niet te vaak gefired (throttle bij input events).
- Server- en client-side foutformaten zijn gelijk.
- Keyboard focusbeheer werkt bij alle foutgevallen.
- Foutteksten voldoen aan leesbaarheid en contrastrichtlijnen.
Call-to-action
Test je implementatie nu met onze WCAG checker: wcagtool.nl/checker. Download ook onze plugin: wcagtool.nl/plugin. Heb je vragen of wil je hulp bij integratie? Gebruik ons contactformulier — we antwoorden binnen 24 uur.
Praktische tip: voeg bij je component library één standaard error-component met props (id, message, live=”polite”) en gebruik die overal—zo voorkom je inconsistenties en maak je testen eenvoudig.