Veelgestelde vragen over WCAG: de antwoorden

Toegankelijke formulieren en focusbeheer — Praktische implementatie | WCAGtool

Toegankelijke formulieren en focusbeheer: praktische implementatie

Formulieren en focusbeheer falen in de praktijk vaak: ontbrekende labels, onduidelijke foutafhandeling, slecht focusbeheer na submit en onbetrouwbare ARIA-implementaties zorgen dat schermlezers en toetsenbordgebruikers vastlopen. Dit leidt tot conversieverlies en juridisch risico.

Wij vertalen WCAG-richtlijnen naar concrete, testbare patterns: complete HTML-voorbeelden, CSS voor zichtbare focus, en JavaScript voor fout- en focusmanagement die je direct in productie kunt gebruiken. Test je pagina meteen met onze WCAG checker/validator en download onze plugin voor automatische scans; bij vragen reageren we binnen 24 uur via het contactformulier.

Het probleem in de praktijk

Ontbrekende of foutieve label-associatie

Veel ontwikkelaars vergeten <label> of gebruiken placeholder als label. Resultaat: schermlezers zien velden niet correct en toetsenbordgebruikers missen context.

Onvoldoende foutinformatie en focus naar foutsummary

Fouten worden vaak alleen visueel aangegeven of met alert-boxen die niet door schermlezers worden opgepikt. Na submit blijft de focus op de knop, in plaats van naar een foutoverzicht te springen.

Slechte focusstyles en tabindex-misbruik

Custom focus-styling wordt weggelaten of tabindex wordt onnodig gebruikt waardoor tab-volgorde breekt en keyboard-ervaringen falen.

Zo los je dit op in code

Basale, correcte HTML-structuur met labels en fieldset

<form id="signup" novalidate><fieldset><legend>Aanmelden nieuwsbrief</legend><div class="form-row"><label for="email">E-mailadres</label><input id="email" name="email" type="email" required aria-required="true" aria-describedby="emailHelp emailError"><div id="emailHelp" class="sr-only">We gebruiken je e-mail alleen voor nieuws</div><div id="emailError" class="error" aria-live="polite"></div></div><div class="form-row"><label for="agree"><input id="agree" name="agree" type="checkbox" required aria-required="true"> Ik ga akkoord met de voorwaarden</label><div id="agreeError" class="error" aria-live="polite"></div></div><div id="formErrors" class="error-summary" role="alert" aria-live="assertive" tabindex="-1"></div><button type="submit">Aanmelden</button></fieldset></form>

CSS: zichtbare en consistente focus

.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);border:0;}input:focus,button:focus,select:focus{outline:3px solid #0b66ff;outline-offset:2px;border-radius:3px;}button:focus{box-shadow:0 0 0 3px rgba(11,102,255,0.15);} /* geen tabindex styling override */

JavaScript: valideren, foutsummary vullen en focus verplaatsen

document.getElementById('signup').addEventListener('submit',function(e){e.preventDefault();const form=this;let errors=[];const email=form.querySelector('#email');const agree=form.querySelector('#agree');const formErrors=document.getElementById('formErrors');document.querySelectorAll('.error').forEach(el=>el.textContent='');if(!email.value||!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.value)){errors.push({field:email,id:'emailError',msg:'Vul een geldig e‑mailadres in.'});}if(!agree.checked){errors.push({field:agree,id:'agreeError',msg:'Je moet akkoord gaan met de voorwaarden.'});}if(errors.length){const ul=document.createElement('ul');errors.forEach(err=>{const li=document.createElement('li');const a=document.createElement('a');a.href='#'+err.field.id;a.textContent=err.msg;a.addEventListener('click',function(ev){ev.preventDefault();err.field.focus();});li.appendChild(a);ul.appendChild(li);document.getElementById(err.id).textContent=err.msg;});formErrors.innerHTML='<h2>Verwerk de volgende fouten</h2>';formErrors.appendChild(ul);formErrors.focus();return;} /* Succes: stuur met fetch of reguliere submit */form.submit();});

ARIA: wanneer en hoe gebruiken

Gebruik ARIA alleen als native HTML niet volstaat. Voor foutsummary gebruik role=”alert” of aria-live=”assertive” en zet tabindex=”-1″ op het error container element zodat je er programmatic focus naar kunt zetten (zie JS voorbeeld).

Checklist voor developers

Formulieren: de snelle checklist

  • Elke input heeft een gerelateerde <label for=”id”> of aria-label/aria-labelledby als er geen zichtbare label is.
  • Gebruik fieldset & legend voor groepen (radio/checkboxgroepen).
  • Gebruik type attributen (email, tel, url) en required/aria-required waar van toepassing.
  • Geef foutmeldingen zowel visueel als via aria-live/role=”alert”.
  • Verplaats focus naar foutsummary met tabindex=”-1″ en element.focus().
  • Geen tabindex>0 tenzij strikt noodzakelijk; volg natuurlijke DOM-volgorde.
  • Vermijd presentational ARIA (role=”button” op echte button) en repareer in plaats van dupliceren.

Performance en progressive enhancement

Implementeer client-side validatie als progressive enhancement; server-side validatie moet dezelfde ARIA- en focus-routines aanroepen zodat foutmeldingen consistent zijn.

Tips voor designers en redacties

Visuele prioriteit en microcopy

Zorg dat foutteksten kort, actiegericht en vlakbij het veld staan. Gebruik visuele kleur + teksticon en altijd een tekstuele foutmelding (geen kleur alleen).

Layout en focusruimte

Reserveer voldoende ruimte voor foutmeldingen zodat content niet verschuift tijdens validatie. Zorg dat focusstijl goed zichtbaar is in het ontwerp (contrast, grootte).

Redactie workflow

Gebruik content templates met duidelijk label-velden en beschrijvingen. Instrueer redacteuren om placeholders niet als enige label te gebruiken.

Hoe test je dit?

Handmatige toetsenbordtest

  1. Tab door het formulier en controleer tab-volgorde en zichtbare focus.
  2. Leave required velden leeg en probeer te submitten; focus moet naar foutsummary gaan en links moeten naar de velden springen.

Screenreader-test

  1. Gebruik NVDA, JAWS of VoiceOver. Luister of labels voor elk veld worden voorgelezen en of foutmeldingen worden aangekondigd.
  2. Controleer aria-describedby en live regions.

Automatische tests

Integreer tools zoals axe-core, pa11y of onze WCAG checker/validator in CI. Gebruik onze plugin om je CMS-pagina’s automatisch te scannen en volg problemen in backlog.

Concrete teststappen met onze tool

Ga naar WCAG checker/validator, voer je URL in en kies “Form Validation & Focus” scan. Download de foutenlijst, pas de hierboven beschreven fixes toe en her-test via onze plugin (download: WCAGtool plugin). Vragen? Gebruik ons contactformulier — we reageren binnen 24 uur.

Extra concrete voorbeelden

Inline error + aria-invalid

<input id="phone" name="phone" type="tel" aria-invalid="true" aria-describedby="phoneError"><div id="phoneError">Voer een geldig telefoonnummer in</div>

Error summary link naar veld

<div id="formErrors" role="alert" tabindex="-1"><ul><li><a href="#email">E-mail ontbreekt of is niet geldig</a></li></ul></div>

Skip link implementatie

<a class="skip-link" href="#main" style="position:absolute;left:-999px;top:auto;" onfocus="this.style.left='0';" onblur="this.style.left='-999px';">Direct naar hoofdinhoud</a>

Laatste praktische tip

Voer direct een scan uit met onze WCAG checker/validator, installeer de plugin voor continue detectie en stuur vragen via het contactformulier — antwoord binnen 24 uur. Kopieer en plak dit minimale testscript in je console om te checken of foutsummary focus werkt:

const e=document.getElementById('formErrors');if(e){e.focus();console.log('Focus naar error summary gezet');}else{console.log('Geen error summary gevonden');}