Hoe redacties content WCAG-proof kunnen maken

Toegankelijke formulieren volgens WCAG — Praktische implementatie | WCAGtool

Toegankelijke formulieren volgens WCAG (praktische implementatie)

Formulieren zijn technisch simpel maar gaan in de praktijk vaak fout: ontbrekende of onduidelijke labels, onsamenhangende foutmeldingen, slechte keyboard- en screenreader-ervaringen en verkeerd gebruik van ARIA. Dat kost gebruikers tijd, levert conversieverlies op en zorgt voor juridische risico’s. Wij richten ons op directe oplossingen die je vandaag kunt implementeren: heldere markup, voorspelbare foutafhandeling en testbare scripts.

Dit artikel biedt stap-voor-stap codevoorbeelden (HTML/CSS/JS), concrete regels voor ontwerp en content, en een testplan dat je direct kunt uitvoeren. Gebruik onze WCAG checker/validator om je pagina live te testen, download onze plugin voor geautomatiseerde scans en neem contact op via het formulier — vragen beantwoordt ons team binnen 24 uur.

Het probleem in de praktijk

Veelvoorkomende fouten

  • Labels ontbreken of zijn visueel niet gekoppeld aan inputs (geen for/id relatie).
  • Foutmeldingen zijn visueel maar niet in de toegankelijkheidsboom (screenreaders missen ze).
  • Focus-management ontbreekt: na submit blijft de gebruiker in het ongewisse en assistive technology verliest context.
  • ARIA wordt onjuist toegepast (role misuse, aria-hidden op essentiële elementen).
  • Complexe widgets zoals datumpickers missen keyboardbediening en labels.

Waarom dit vaak gebeurt

  • Designers en developers denken vanuit visueel ontwerp, niet vanuit assistive workflows.
  • Ontbreken van een standaard component-library met correcte ARIA en tests.
  • Content-editors plakken foutmeldingen als afbeelding of gewone tekst zonder semantiek.

Zo los je dit op in code

Fundamentele HTML-structuur: semantic labels en hintteksten

Gebruik altijd een label gekoppeld via for/id en voeg een helptekst toe met aria-describedby. Voor required velden gebruik required attribuut en een visuele indicator die ook voor screenreaders zichtbaar is.

<form id="signupForm" novalidate>
  <div class="form-row">
    <label for="email">E-mailadres <span aria-hidden="true">*</span><span class="sr-only">verplicht</span></label>
    <input id="email" name="email" type="email" required aria-describedby="emailHelp emailError" />
    <div id="emailHelp" class="hint">We sturen alleen belangrijke berichten</div>
    <div id="emailError" class="error" aria-live="polite"></div>
  </div>
  <button type="submit">Aanmelden</button>
</form>

CSS: visually-hidden class en duidelijke foutstijl

.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;}
.error{color:#b00020;margin-top:0.25rem;}
input[aria-invalid="true"]{outline:2px solid #b00020;}

JavaScript: client-side validatie, focus management en ARIA updates

Gebruik progressive enhancement: laat browser-validatie werken, maar voeg JS toe voor consistente foutmeldingen, aria-invalid en focus naar de eerste fout.

document.getElementById('signupForm').addEventListener('submit', function(e){
  e.preventDefault();
  var form = e.target;
  var firstInvalid = null;
  var fields = form.querySelectorAll('input,select,textarea');
  fields.forEach(function(f){
    var errorEl = document.getElementById(f.id + 'Error');
    if(!f.checkValidity()){
      f.setAttribute('aria-invalid','true');
      if(errorEl) errorEl.textContent = f.validationMessage || 'Controleer dit veld';
      if(!firstInvalid) firstInvalid = f;
    } else {
      f.removeAttribute('aria-invalid');
      if(errorEl) errorEl.textContent = '';
    }
  });
  if(firstInvalid){
    firstInvalid.focus();
    // extra: verplaats focus naar een algemene foutcontainer indien gewenst
    return false;
  }
  // submit via fetch of gewoon form.submit()
  form.submit();
}, false);

Server-side foutmeldingen: maak ze semantisch

Wanneer server-side validatie faalt, geef een status 400 en stuur een JSON met velderrors. Render deze terug met dezelfde id’s en update aria-live gebieden.

{ "errors": { "email": "Dit e-mailadres is al in gebruik", "password": "Wachtwoord te kort" } }

Front-end voorbeeld om serverfouten te tonen:

function renderServerErrors(errors){
  Object.keys(errors).forEach(function(name){
    var el = document.getElementById(name);
    var err = document.getElementById(name + 'Error');
    if(el){ el.setAttribute('aria-invalid','true'); }
    if(err){ err.textContent = errors[name]; }
  });
  var first = document.querySelector('[aria-invalid="true"]');
  if(first) first.focus();
}

Checklist voor developers

  • Labels: elk input heeft een <label for=”id”> of aria-label/aria-labelledby als visueel verborgen.
  • Hints: gebruik aria-describedby voor helpteksten en foutmeldingen.
  • Fouten: foutberichten in element met role=”alert” of aria-live=”polite” en gekoppeld via id.
  • Keyboard: alle controls zijn focusbaar en werken zonder muis.
  • Focus: bij fout na submit focus naar eerste foutveld.
  • ARIA: gebruik ARIA alleen als native HTML niet volstaat; avoid role misuse.
  • Server: return JSON met veld-fouten en koppel deze aan inputs.
  • Automatiseer: draai onze WCAG checker/validator en installeer de WCAGtool plugin voor CI.

Tips voor designers en redacties

Ontwerpregels

  • Zorg voor voldoende kleurcontrast van labels en fouten (controleer met onze checker).
  • Gebruik consistente plaatsing: fout onder het veld of boven het formulier, niet beiden.
  • Maak required-indicator ook tekstueel beschikbaar (bijv. “verplicht”).

Contentrichtlijnen

  • Houd foutmeldingen kort, concreet en actiegericht: “Vul een geldig e-mailadres in” vs “Ongeldige invoer”.
  • Vermijd vage meldingen: geef aan wat fout is en hoe te herstellen.
  • Schrijf helpteksten met concrete voorbeelden en formaat (bijv. “DD-MM-JJJJ”).

Component libraries

Lever componenten met ingebouwde ARIA, tests en documentatie. Wij leveren een voorbeeldcomponent die je kunt plakken:

<template id="wcag-input">
  <label part="label"><slot name="label"></slot></label>
  <input part="input"></input>
  <div part="error" aria-live="polite"></div>
</template>

Hoe test je dit?

Automatische tests

  1. Draai onze WCAG checker/validator op de live pagina voor snelle feedback.
  2. Integreer de WCAGtool plugin in je CI-pipeline voor regressiecontrole.
  3. Gebruik axe-core of Lighthouse in je test-suite en verifieer aria-live en focus-management via end-to-end tests.

Handmatige tests (quicklist)

  1. Toetsenbordvolgorde: navigeer met Tab en Shift+Tab, alle controls moeten bereikbaar zijn in logische volgorde.
  2. Screenreader-run: met NVDA/VoiceOver lees je labels en foutmeldingen voor en zorg dat aria-describedby en aria-live werken.
  3. Verwijder CSS: check of formulier nog steeds bruikbaar is zonder styling (structurele toegankelijkheid).
  4. Simuleer langzame netwerken: zorg dat serverfouten correct terugkomen en de gebruiker feedback krijgt.

E2E voorbeeld (Puppeteer/Playwright) voor focus na submit

// Playwright voorbeeld
const { test, expect } = require('@playwright/test');
test('focus moves to first invalid field', async ({ page }) => {
  await page.goto('https://jouwsite.example/form');
  await page.click('button[type="submit"]');
  const focused = await page.evaluate(() => document.activeElement.id);
  expect(focused).toBe('email'); // pas aan naar jouw eerste required veld id
});

Checklist testresultaten

  • Foutmeldingen verschijnen binnen 1 seconde en zijn zichtbaar in DOM.
  • Screenreader leest foutmelding direct bij focus of via aria-live.
  • Geen aria-hidden op essentiële form controls.
  • Contrast en touch-targets voldoen aan WCAG AA/AAA waar nodig.

Test direct je pagina met onze WCAG checker/validator, download de plugin voor automatische scans en neem contact op via het contactformulier — we beantwoorden vragen binnen 24 uur.

Praktische code-check die je direct kunt toepassen

Plak dit korte script in je pagina en klik submit: het markeert invalide velden, toont foutmeldingen en zet focus op het eerste probleem.

(function(){var f=document.querySelector('form');if(!f)return;f.addEventListener('submit',function(e){e.preventDefault();var first=null;Array.from(f.elements).forEach(function(el){var err=document.getElementById(el.id+'Error');if(!el.checkValidity()){el.setAttribute('aria-invalid','true');if(err)err.textContent=el.validationMessage||'Controleer dit veld';if(!first)first=el;}else{el.removeAttribute('aria-invalid');if(err)err.textContent='';}});if(first){first.focus();return;}f.submit();});})();

Probeer nu je eigen formulier met onze checker en ontvang binnen 24 uur implementatieadvies via het contactformulier. Download ook meteen de plugin om dit automatisch te laten scannen in je CI.