Toegankelijke formulieren: labels, errors en focuscorrectie in de praktijk
Formulieren zijn één van de meest voorkomende plekken waar WCAG-regels in de praktijk misgaan: ontbrekende labels, onbegrijpelijke foutmeldingen, slechte focusflow en ongebruiksvriendelijke ARIA-implementaties zorgen voor blokkades bij gebruikers met assistieve technologie. Dit artikel behandelt concrete, testbare oplossingen zodat developers, frontend engineers, UX/UI designers en redacties direct aan de slag kunnen.
Wij van wcagtool.nl vertalen WCAG naar werkbare code-snippets, checklists en teststappen. Test je site direct met onze WCAG checker/validator, download onze plugin voor CI-checks en neem contact op via het contactformulier — we reageren binnen 24 uur.
Het probleem in de praktijk
Ontbrekende of visueel verborgen labels, foutmeldingen die voor screenreaders onvindbaar zijn, en focus die niet naar het eerste foutveld springt: dat zijn de meest voorkomende issues. Ontwerpers kiezen vaak alleen een visueel hint in plaats van een echte label, en developers zetten aria-attrs zonder de juiste technieken voor focus- en live-announce. De uitkomst: formulieren die in visuele tests werken, maar falen voor toetsenbordgebruikers en screenreaders.
- Labels niet gekoppeld via <label for=”id”> of aria-labelledby
- Inline fouten zonder aria-describedby of role=”alert”
- Geen focusmanagement na submit — gebruiker blijft “vast” staan
- Contrast en focus-indicatoren niet zichtbaar
Test je formulier nu met onze WCAG checker/validator of installeer de plugin voor continue controle.
Zo los je dit op in code
1) Altijd correcte labels
Gebruik een <label> gekoppeld aan het input-id. Als je visueel geen label wilt tonen, gebruik een toegankelijke visually-hidden class.
<style>.sr-only{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}</style><label for="email" class="sr-only">E-mailadres</label><input id="email" name="email" type="email" required aria-required="true">
2) Foutmeldingen die screenreaders en keyboarders zien
Gebruik aria-describedby op het input-element, en role=”alert” in de foutcontainer zodat assistive tech de fout aankondigt. Markeer velden met aria-invalid=”true”.
<div class="field"><label for="phone">Telefoonnummer</label><input id="phone" name="phone" type="tel" aria-describedby="phone-error" aria-invalid="false"><div id="phone-error" class="error" role="alert" aria-live="assertive" hidden>Voer een geldig telefoonnummer in</div></div>
3) Focus naar eerste foutveld na validatie
Gebruik JavaScript om client-side of server-side errors te focussen naar het eerste onjuist veld en zet aria-invalid. Dit verhoogt bruikbaarheid voor toetsenbordgebruikers en screenreaders.
function focusFirstError(errors){const first = document.querySelector('[data-error="true"],[aria-invalid="true"]') || document.querySelector('.error:first-of-type');if(first){const field = first.closest('.field')?.querySelector('input,select,textarea') || first;field.focus();}
4) Voorbeeld: eenvoudige client-side validatie (HTML + JS)
<form id="signup"><div class="field"><label for="name">Naam</label><input id="name" name="name" required aria-required="true" aria-describedby="name-error"><div id="name-error" class="error" role="alert" aria-live="assertive" hidden>Naam is verplicht</div></div><div class="field"><label for="email">E-mail</label><input id="email" name="email" type="email" required aria-required="true" aria-describedby="email-error"><div id="email-error" class="error" role="alert" aria-live="assertive" hidden>Vul een geldig e-mailadres in</div></div><button type="submit">Verstuur</button></form><script>document.getElementById('signup').addEventListener('submit',function(e){e.preventDefault();let firstError=null;['name','email'].forEach(id=>{const el=document.getElementById(id);const err=document.getElementById(id+'-error');if(!el.checkValidity()){el.setAttribute('aria-invalid','true');err.hidden=false;err.textContent=el.validationMessage;el.setAttribute('data-error','true');firstError=firstError||el}else{el.removeAttribute('aria-invalid');err.hidden=true;el.removeAttribute('data-error')} });if(firstError){firstError.focus();return} // submit form via AJAX of normale submit hier });</script>
5) Focus styles en zichtbaarheid
Zorg dat focus zichtbaar is, ook als de browser custom focus gebruikt. Gebruik :focus-visible voor moderne browsers en fallback voor focus.
input:focus,button:focus{outline:3px solid #005fcc;outline-offset:2px}input[aria-invalid="true"]{border-color:#d93025;background:#fff6f6}
Checklist voor developers
- Labels: elk input-element heeft een zichtbare of sr-only <label> gekoppeld via for/id of aria-labelledby.
- Fouten: gebruik aria-describedby en role=”alert” + aria-live voor fouttekst.
- aria-invalid: zet op true bij ongeldige velden, false of verwijder bij validatie ok.
- Focus: bij submit focus naar eerste foutveld en trap keyboard focus niet vast in modals.
- Keyboard: alle interacties (submit, help, selecties) werken met Enter/TAB/Space.
- Contrast: error states, placeholders en focus-indicatoren voldoen aan contrastregels.
- HTML5-validatie: combineer native validation met custom messaging voor consistentie.
- Test automatisering: run onze WCAG checker/validator en integreer de plugin in CI.
Gebruik de WCAG checker op https://wcagtool.nl en download onze plugin voor automatische builds.
Tips voor designers en redacties
1) Schrijf heldere, korte foutmeldingen
Vermijd generieke teksten als “Ongeldige invoer”. Geef oplossing: “Voer een geldig e-mailadres in zoals naam@voorbeeld.nl”. Plaats foutmelding direct in de context.
2) Visuele signalen én tekst
Kleur alleen is niet voldoende. Combineer kleur met iconen, expliciete tekst en focus-indicatoren. Test met grijswaarden en screenreaders.
3) Placeholder vs label
Gebruik placeholders alleen als voorbeeld, niet als vervanging van het label. Content-redacteuren: controleer dat voorbeeldteksten niet lijken op fouten of waarden.
4) Microcopy en instructies
Plaats instructies buiten het inputveld, gekoppeld via aria-describedby. Voor langere instructies gebruik een kort summier label en link naar uitgebreide hulp.
Hoe test je dit?
Handmatige tests (snel en effectief)
- Toetsenbord-test: navigeer alleen met TAB en SHIFT+TAB, activeer alle controls met Enter/Space. Controleer dat focus zichtbaar blijft en logische volgorde klopt.
- Screenreader-test: open NVDA/VoiceOver en loop door formulier, controleer of labels, foutmeldingen en aria-live aankondigingen hoorbaar/bruikbaar zijn.
- Foutflow: verzend formulier met lege of ongeldige velden, controleer dat focus naar eerste fout springt en fouttekst wordt aangekondigd.
- Contrast: controleer foutrand en focus-indicator met contrastcheckers (minimaal 3:1 voor UI-componenten, 4.5:1 voor tekst).
Automatische tests en CI
Gebruik onze WCAG checker/validator voor een snelle scan. Integreer de plugin in je build pipeline. Gebruik daarnaast axe-core in unit/e2e tests. Voorbeeld met Cypress + axe:
import 'cypress-axe';cy.visit('/formulier');cy.injectAxe();cy.checkA11y(null,{runOnly:{type:'tag',values:['wcag2aa']}});
Server-side validation en accessibility
Bij server-side errors: stuur fout-IDs terug en render foutblokken met aria-describedby en role=”alert”. Zorg dat de responsieve pagina de focus verplaatst naar het foutpaneel bij her-render.
// server response (JSON) { "errors": { "email":"Ongeldig e-mailadres" }, "focus":"email" } // client-side: focus naar field met id response.focus
Laatste praktische tip
Voeg deze utility-functie toe voor consistente foutafhandeling: zet aria-invalid, update fouttekst, toon role=”alert” en focus op eerste fout. Test direct met onze WCAG checker/validator en installeer de plugin voor continue monitoring. Vragen? Gebruik het contactformulier op wcagtool.nl — we antwoorden binnen 24 uur.
function showFieldError(id,message){const el=document.getElementById(id);const err=document.getElementById(id+'-error');if(!el||!err) return;err.textContent=message;err.hidden=false;err.setAttribute('role','alert');el.setAttribute('aria-invalid','true');el.setAttribute('aria-describedby',id+'-error');el.focus();}
Direct testen: voer je URL in op https://wcagtool.nl, download onze plugin en vraag ons om hulp via het contactformulier — reactie binnen 24 uur.