Keyboard-toegankelijkheid & focusbeheer: direct toepasbare oplossingen
Keyboard-toegankelijkheid en focusbeheer zijn in de praktijk vaak fout ingericht: ontbrekende skip-links, onlogische tabvolgorde, custom controls zonder keyboard-ondersteuning en gebrekkige focusstijlen. Dat leidt tot onbruikbare interfaces voor gebruikers die geen muis gebruiken.
Wij lossen dit op met concrete, testbare codevoorbeelden, checklists en direct inzetbare testinstructies. Test je site altijd eerst automatisch met onze WCAG checker/validator, installeer onze plugin voor IDE/browser feedback en stuur vragen via het contactformulier (antwoord binnen 24 uur).
Het probleem in de praktijk
Veelvoorkomende fouten
- Geen skip-link of skip-link wordt verborgen door CSS.
- Interactie-elementen gebruiken geen semantische elementen (div/button) of missen keyboard events.
- Modals en dialogs vangen geen focus (focus trap ontbreekt), of geven focus niet terug bij sluiten.
- Custom controls missen ARIA-attributen en keyboard-handlers.
- Focus-styles worden weggehaald met outline: none zonder alternatief.
Waarom dit gebruikers blokkeert
Gebruikers die alleen toetsenbord gebruiken moeten alle interacties bereiken en begrijpen welke element focus heeft. Zonder juiste tabvolgorde, focus-indicatoren en keyboard-ondersteuning stopt taakuitvoering.
Zo los je dit op in code
Stap 1 — Voeg een zichtbare skip-link toe
Implementatie die direct werkt en zichtbaar wordt bij focus:
<a class="skip-link" href="#main">Sla navigatie over</a><br><!-- CSS --><br>.skip-link {position:absolute;left:-9999px;top:auto;width:1px;height:1px;overflow:hidden;} .skip-link:focus {position:static;left:auto;width:auto;height:auto;padding:0.5rem;background:#fff;border:2px solid #000;z-index:1000;}
Stap 2 — Gebruik semantische elementen en tabindex verstandig
Gebruik <button> voor knoppen, <a href> voor links. Vermijd tabindex="0" op non-interactieve elementen tenzij je ze rol geeft en keyboard handlers.
<!-- Correct --><br><button type="button">Verstuur</button><br><!-- Slecht voorbeeld, vermijd --><br><div role="button" tabindex="0">Klik</div> <!-- alleen als je keyboard handlers toevoegt -->
Stap 3 — Focus-styles: altijd zichtbaar
Gebruik focus-visible of custom outline. Verwijder nooit focus zonder alternatief.
/* CSS */<br>:focus {outline:3px solid #0a84ff;outline-offset:2px;}@media (hover: none) { :focus {outline:2px dashed #000;} }/* Optioneel: prefers-reduced-motion niet voor focus */
Stap 4 — Focus trap voor modals (klein, testbaar script)
Script dat tab-cycling in modal afdwingt en focus teruggeeft bij sluiten:
// Open modal: focus naar eerste focusable, bij sluiten: teruggeven aan opener<br>function trapFocus(modal, opener) { const FOCUSABLE = 'a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex="-1"])'; const nodes = modal.querySelectorAll(FOCUSABLE); const first = nodes[0]; const last = nodes[nodes.length-1]; function handleKey(e) { if (e.key === 'Tab') { if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); } else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); } } if (e.key === 'Escape') { closeModal(); } } function openModal() { modal.style.display = 'block'; modal.setAttribute('aria-hidden','false'); first.focus(); document.addEventListener('keydown', handleKey); } function closeModal() { modal.style.display = 'none'; modal.setAttribute('aria-hidden','true'); document.removeEventListener('keydown', handleKey); opener.focus(); } return { open: openModal, close: closeModal };}
Stap 5 — ARIA correct en alleen waar nodig
Gebruik roles en aria-attributes om gedrag aan te geven, niet om semantiek te vervangen. Voor een custom toggle:
<button id="menuToggle" aria-expanded="false" aria-controls="mainMenu">Menu</button><br><nav id="mainMenu" hidden>...</nav><br>// JS togglen<br>const btn = document.getElementById('menuToggle'); const menu = document.getElementById('mainMenu'); btn.addEventListener('click', () => { const expanded = btn.getAttribute('aria-expanded') === 'true'; btn.setAttribute('aria-expanded', String(!expanded)); menu.hidden = expanded; });
Stap 6 — Tabvolgorde: logica boven visuele volgorde
Stel DOM-structuur in op de logische volgorde of gebruik CSS order alleen als tabindex en focus logisch blijven. Tabindex="0" voor focusable, vermijd positieve tabindex waardes.
Checklist voor developers
- Skip-link: aanwezig en zichtbaar bij focus.
- Alle interactieve elementen: semantische tag of role + keyboard handlers.
- Geen outline: none zonder alternatief.
- Modals/dialogs: focus trap, aria-hidden management en focus teruggeven.
- Custom widgets: ARIA attributes correct (role, aria-checked, aria-expanded, aria-controls).
- Tabindex: alleen 0 of -1; geen positieve waarden.
- Controleer zichtbaarheid van focus in alle browsers en zoom-levels.
- Automatische tests: run onze WCAG checker/validator en browser devtools-accessibility audits.
Tips voor designers en redacties
Designers: zichtbare focus in design system
Geef designers component-varianten met focus- en hover-states. Lever tokens voor outline-color, outline-width en offset zodat developers consistente focusstijlen kunnen implementeren.
Redacties: links en knoppen begrijpelijk labelen
Gebruik duidelijke, korte linkteksten en vermijd ‘klik hier’. Zorg dat link-context ook zonder surrounding tekst duidelijk is (WCAG 2.4.4 Link Purpose (in context)).
UX-tip: test flows keyboard-only
Systeem flows (inloggen, formulier, zoeken) run je dagelijks keyboard-only. Noteer punten waar tabvolgorde verwarrend is en los die op in DOM-structuur.
Hoe test je dit?
Handmatige toetsenbordtests (practische stappen)
- Druk Tab door de pagina; alle focusable items moeten bereikbaar zijn in logische volgorde.
- Test Shift+Tab voor reverse navigatie.
- Open/sluide modals met alleen toetsenbord; Esc sluit en focus keert terug naar opener.
- Activeer alle controls (buttons, links, form elements) met Enter en Space waar van toepassing.
Screenreader & assistive tech
Test met NVDA (Windows) en VoiceOver (macOS/iOS). Controleer of ARIA-attributes correcte informatie geven: aria-expanded, aria-controls, aria-hidden, aria-live wanneer dynamische content verandert.
Automatische tools en onze validator
Start met onze WCAG checker/validator voor snelle issues. Gebruik daarnaast browser Accessibility Inspector en Lighthouse. Automatische tools vangen ~30-40% van issues; combineer met handmatige tests hierboven.
Testcases die je direct kunt uitvoeren
- Case: modal focus trap — open modal, Tab 10 keer: focus blijft in modal.
- Case: keyboard-only form — vul en submit alle velden zonder muis.
- Case: skip-link — Tab vanaf paginabegin, activeer skip-link en controleer focus op <main id="main">.
Laatste praktische tip
Implementeer een kleine CI-check: run onze validator tegen pull requests en voeg een premerge checklist met keyboard-tests toe aan je repo. Download onze plugin voor VS Code/Chrome om fouten vroeg te vangen. Vragen? Gebruik het contactformulier — we reageren binnen 24 uur.
Direct beginnen: test je site nu met onze validator: https://wcagtool.nl/validator