WCAG en CMS-systemen: WordPress

Toegankelijke formulieren en foutmeldingen — Praktische implementatie | wcagtool.nl

Toegankelijke formulieren en foutmeldingen

Formulieren zijn in de praktijk één van de grootste pijnpunten voor WCAG-compliance: labels ontbreken of zijn onduidelijk, foutmeldingen worden visueel weergegeven maar niet aan assistive tech gemeld, en keyboard- of focusflow faalt bij dynamische validatie. Dat zorgt voor uitval, frustratie en juridische risico’s.

Wij helpen developers, designers en redacties met concrete, stap-voor-stap oplossingen: semantische HTML, correcte ARIA-attributen, focusmanagement en testbare JavaScript-patronen. Gebruik direct de voorbeelden en test je site met onze WCAG checker/validator of installeer onze plugin — vragen? Contact via het contactformulier, reactie binnen 24 uur.

Het probleem in de praktijk

Veelvoorkomende fouten

  • Geen of onjuiste <label> koppeling met invoervelden.
  • Visuele foutmeldingen zonder ARIA-live of focus naar fout.
  • Gebruik van placeholders als vervanging van labels.
  • Onvoldoende contrast van fout- of helptekst.
  • Dynamische validatie zonder passende roles (aria-invalid, aria-describedby, role="alert").

Waarom dat fout gaat

Veel teams sturen op visuele mockups en denken dat client-side scripts alles “fixen”, maar screenreader-gebruikers en keyboard-only users missen de semantiek. Ook ontbreken vaak regressietests waarmee deze cases automatisch falen.

Zo los je dit op in code

1) Basisformulieren: semantische HTML en labels

<form id="signupForm"><br>  <div class="form-row"><br>    <label for="email">E-mailadres</label><br>    <input id="email" name="email" type="email" required aria-describedby="email-help email-error"><br>    <div id="email-help" class="help">We sturen geen spam.</div><br>    <div id="email-error" class="error" aria-live="assertive"></div><br>  </div><br>  <button type="submit">Aanmelden</button><br></form>

Uitleg

Gebruik vaste id’s en verwijs met for en aria-describedby. Error-elementen krijgen aria-live="assertive" zodat screenreaders wijzigingen direct aankondigen.

2) Client-side validatie: aria-invalid en focusmanagement

document.getElementById('signupForm').addEventListener('submit', function(e){<br>  e.preventDefault();<br>  const email = document.getElementById('email');<br>  const emailError = document.getElementById('email-error');<br>  email.removeAttribute('aria-invalid');<br>  emailError.textContent = '';<br>  if(!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.value)) {<br>    email.setAttribute('aria-invalid','true');<br>    emailError.textContent = 'Vul een geldig e‑mailadres in.';<br>    emailError.classList.add('visible');<br>    email.focus(); // focus naar het foutveld<br>    return; // stop verzending<br>  }<br>  // verstuur AJAX of submit<br>});

Uitleg

Zet aria-invalid="true" op het input als de waarde niet klopt, update de error-container (die aria-live heeft) en breng focus naar het relevante veld — belangrijk voor keyboard- en screenreader-gebruikers.

3) Complexe formulieren en meerdere foutmeldingen

// Voor meerdere fouten: maak een overzicht en link naar velden via id's<br>function showErrors(errorMap){<br>  // errorMap = { fieldId: 'Foutmelding' }<br>  const summary = document.getElementById('form-error-summary');<br>  summary.innerHTML = '<h2>Er zijn fouten in het formulier</h2><ul>';<br>  Object.keys(errorMap).forEach(id => {<br>    const msg = errorMap[id];<br>    const li = document.createElement('li');<br>    const a = document.createElement('a');<br>    a.href = `#${id}`;<br>    a.textContent = msg;<br>    a.addEventListener('click', function(e){ e.preventDefault(); document.getElementById(id).focus(); });<br>    li.appendChild(a);<br>    summary.querySelector('ul').appendChild(li);<br>    document.getElementById(id).setAttribute('aria-invalid','true');<br>    const errEl = document.getElementById(id + '-error'); errEl.textContent = msg;<br>  });<br>  summary.setAttribute('tabindex','-1'); summary.focus(); // focus naar samenvatting<br>}

Uitleg

Een foutensamenvatting bovenaan het formulier met links naar de velden verbetert navigatie; zet tabindex -1 en focus naar de samenvatting zodat schermlezers en keyboard-gebruikers direct de problemen weten.

4) CSS: zichtbare focus en contrast

.form-row input:focus { outline: 3px solid #0b66ff; outline-offset: 2px; } .error { color: #b00020; } .error.visible { display: block; } /* Verberg fouten niet visueel voor screenreaders */ .error[aria-hidden="true"] { display:none; }

Uitleg

Zorg dat focus duidelijk zichtbaar is (niet alleen box-shadow die wegvalt bij hoge-contrastinstellingen) en dat foutkleurcontrast voldoet aan WCAG AA/AAA afhankelijk van tekstgrootte.

Checklist voor developers

  • Alle inputs hebben een gekoppeld <label> of aria-label/aria-labelledby.
  • Gebruik required en type-attributen (email, tel, url) naast JS-validatie.
  • Foutberichten hebben een id en worden genoemd in aria-describedby.
  • Bij fouten: zet aria-invalid="true" op het invoerveld; verwijder het wanneer valide.
  • Bij directe foutmelding wijziging: aria-live="assertive" of role="alert" gebruiken.
  • Toon een foutensamenvatting met links naar velden en focus ernaartoe.
  • Zorg voor zichtbare focusstijlen en voldoende kleurcontrast.
  • Automatiseer tests (axe-core, pa11y) en gebruik onze WCAG checker/validator bij elke CI-run.

Tips voor designers en redacties

Designers — componentrichtlijnen

  • Maak formuliercomponenten met vaste plekken voor help- en error-teksten (altijd ruimte reserveren om layout-shift te voorkomen).
  • Ontwerp foutensamenvatting en individuele fouten als klikbare links naar velden.
  • Documenteer focusstijlen in design-system — gebruik niet alleen kleur om status te communiceren.

Redacties — contentrichtlijnen

  • Schrijf korte, concrete foutmeldingen: wat is fout en hoe los je het op. Vermijd technische termen.
  • Gebruik actieve taal en voorbeeldvalidatie: “Gebruik dit formaat: 0612345678”.
  • Houd helptekst bij invoer beknopt en nuttig; zet uitgebreide instructies in een apart help-venster met aria-controls/aria-expanded als nodig.

Hoe test je dit?

Handmatige stappen

  1. Keyboard-only: navigeer naar elk veld, vul foutieve data in, verstuur en controleer of focus en samenvatting logisch zijn.
  2. Screenreader (NVDA/VoiceOver): lees het formulier, voer fout in, controleer dat foutmelding wordt aangekondigd en dat de samenvatting wordt voorgelezen.
  3. Contrast: controleer fout- en hulptekst met contrastchecker (WCAG AA minimaal 4.5:1 voor normale tekst).
  4. Responsief: test op mobiel en tablet; zorg dat foutensamenvatting niet buiten viewport valt zonder mogelijkheid om ernaartoe te navigeren.

Automatische tests

Integreer deze checks in CI met tools zoals axe-core en pa11y. Voorbeeld npm-script:

"scripts": { "test:a11y": "pa11y-ci --config ./pa11yci.js" }

Gebruik daarnaast onze WCAG checker/validator op wcagtool.nl of installeer onze browser-plugin voor snelle lokale scans. Draai scans na elke release.

Verifieer met concrete testcases

  • Case: leeg required veld — verwacht: focus naar veld, aria-invalid, samenvatting met link.
  • Case: meerdere fouten — verwacht: samenvatting met één lijst, elke link verplaatst focus naar correct veld.
  • Case: dynamische validatie terwijl gebruiker typt — verwacht: aria-live-updates, geen break van keyboardflow.

Run deze cases handmatig en als geautomatiseerde e2e-tests (Cypress + axe plugin). Vergeet niet om onze WCAG checker/validator in te zetten en de plugin te downloaden — test direct je site op wcagtool.nl.

Vraag hulp of stuur voorbeelden van je implementatie via ons contactformulier; we beantwoorden binnen 24 uur en geven concrete code-aanpassingen.

Laatste praktische tip: voeg dit kleine helper-snippet toe in je project om bij submit alle error-containers te resetten en focus consistent te beheren:

function resetFormErrors(form){const errors = form.querySelectorAll('.error');errors.forEach(e => { e.textContent=''; e.classList.remove('visible'); });const invalids = form.querySelectorAll('[aria-invalid="true"]');invalids.forEach(i => i.removeAttribute('aria-invalid'));}

Test je implementatie meteen met onze online WCAG checker/validator op wcagtool.nl, of installeer onze plugin voor snelle lokale scans. Heb je vragen? Gebruik het contactformulier — we reageren binnen 24 uur.