Niet iedereen gebruikt een muis of trackpad om een website te bedienen. Mensen met een tremor, RSI, dwarslaesie of een visuele beperking zijn afhankelijk van het toetsenbord of hulpmiddelen die toetsaanslagen gebruiken. Als een website daar niet op is ingericht, wordt het voor hen onbruikbaar.
Ook voor mensen zonder beperking is goede toetsenbordondersteuning waardevol. Denk aan een sneltoets om snel een actie uit te voeren of het gebruik van Tab om gemakkelijk door een formulier te navigeren.
In dit artikel leg ik je alles uit over toetsenbordtoegankelijkheid.
Deze toetsen moet je kennen
| Taak | Toets |
|---|---|
| Naar het volgende bedieningselement | Tab |
| Naar het vorige bedieningselement | Shift + Tab |
| Link activeren | Enter |
| Knop activeren | Enter of spatie |
| Selectievakje selecteren | Spatie |
| Navigeren tussen keuzerondjes | ↑ (pijltje naar boven) en ↓ (pijltje naar beneden) |
| Keuzerondje selecteren | Spatie |
| Keuzelijst openen | Spatie |
| Navigeren in een keuzelijst | ↑ (pijltje naar boven) en ↓ (pijltje naar beneden) |
| Element sluiten | Esc |
De WAI-ARIA Authoring Practices Guide beschrijft de verwachte toetsenbordinteractie voor complexe componenten als tabpanelen, boomstructuren en menu’s.
Zorg dat alle functionaliteit werkt met het toetsenbord
Succescriterium 2.1.1 Toetsenbord eist dat alle functionaliteit bedienbaar is met een toetsenbordinterface. Dit geldt voor alle bedieningselementen: links, knoppen, formulierelementen en maatwerk componenten.
De term “toetsenbordinterface” betekent hier niet alleen een fysiek toetsenbord. Het omvat ook spraakherkenningsoftware, zuig-en-blaasschakelaars en schermtoetsenborden. Deze hulpmiddelen sturen ook toetsaanslagen naar de browser. Als jouw website via het toetsenbord werkt, dan werkt het ook met deze hulpmiddelen.
Gebruik semantische HTML-elementen
Gebruik zo veel mogelijk standaard HTML-elementen. Een <button> werkt automatisch met Enter en Spatie. Een <a>-element werkt met Enter. Een <input>, <select> en <textarea> zijn automatisch focusbaar. Bouw je een interactief element met een <div> of <span>? Dan moet je zelf zorgen voor focusbaarheid (met tabindex="0"), toetsenbordafhandeling (met JavaScript) en een toegankelijke rol (met ARIA). Dat is veel extra werk en foutgevoelig. Gebruik daarom liever gewoon het juiste HTML-element. (Lees ook de eerste regel van ARIA.)
Let op: Een <a>-element is alleen bereikbaar met het toetsenbord als het een niet-leeg href-attribuut heeft. Een <a> zonder href is niet focusbaar en wordt door schermlezers ook niet als link aangekondigd.
<!-- Fout voorbeeld -->
<a onclick="navigate()">Volgende pagina</a>
<!-- Goed voorbeeld -->
<a href="/volgende-pagina">Volgende pagina</a>
Gebruik ook geen <div> als bedieningselement:
<!-- Fout voorbeeld -->
<div onclick="save()">
Opslaan
</div>
<!-- Goed voorbeeld -->
<button type="button" onclick="save()">
Opslaan
</button>
Succescriterium 2.1.1 vereist niet dat bedieningselementen de verwachte toetsenbordinteracties volgen. Dus een aangepaste knop die alleen op Enter reageert (en niet ook op Spatie) voldoet nog steeds. Maar het is wél een best practice om Enter én Spatie te ondersteunen, omdat gebruikers dat verwachten.
Scrollbare gebieden focusbaar maken
Codeblokken, kaarten en andere gebieden met overflow kunnen zo lang worden dat je erin moet scrollen. Met een muis scroll je met het wieltje. Maar toetsenbordgebruikers kunnen alleen scrollen met de pijltoetsen als het gebied focus heeft. Voeg tabindex="0" toe aan het scrollbare element.
Als het kan, geef het element dan ook een toegankelijke naam met role="region" en aria-label. Zo kunnen schermlezers aankondigen wat het gebied is.
Geen specifieke timing vereist
Gebruikers mogen niet afhankelijk zijn van hoe snel ze typen of hoe lang ze een toets ingedrukt houden. Een functie die vereist dat je heel snel een toetscombinatie maakt, voldoet niet. Dit is belangrijk voor mensen die plaktoetsen (Sticky Keys) gebruiken.
(Plaktoetsen is een toegankelijkheidsfunctie in Windows/macOS waarmee je sneltoetsen (zoals Ctrl + C) kan typen door de toetsen na elkaar in te drukken in plaats van tegelijkertijd.)
Bied alternatieven voor gebaren en beweging
Niet iedereen kan swipen, slepen of een telefoon schudden. Functies die een complex gebaar of een fysieke beweging vereisen, moeten ook op een eenvoudige manier werken: met een enkele klik, tik of toetsaanslag. Denk aan knoppen om items te sorteren in plaats van drag-and-drop, een zoomknop in plaats van pinch-to-zoom, of een wissen-knop in plaats van het schudden van een telefoon.
Drie succescriteria zorgen dat deze functies voor iedereen toegankelijk zijn:
| Succescriterium | Wat je moet doen |
|---|---|
| 2.5.1 Aanwijzergebaren (niveau A) | Bied een alternatief voor swipen en pinch-to-zoom. |
| 2.5.4 Bewegingsactivering (niveau A) | Zorg dat functies die reageren op beweging ook met een knop werken en kunnen worden uitgeschakeld. |
| 2.5.7 Sleepbewegingen (niveau AA) | Bied een alternatief voor drag-and-drop. |
Veelgemaakte fouten
| Fout | Probleem | Oplossing |
|---|---|---|
<div> als bedieningselement | Werkt niet met toetsenbord | Gebruik <a>, <button> of <input> |
tabindex="-1" op een bedieningselement | Element is niet meer bereikbaar via Tab | Verwijder het tabindex-attribuut |
Alleen onmousedown of onmouseover | Toetsenbordgebruikers kunnen de functie niet activeren | Voeg toetsenbord-events toe |
| Maatwerk component zonder ARIA | Schermlezer weet niet wat het is | Voeg role, tabindex en toetsenbordafhandeling toe |
| Hover-only menu | Submenu verschijnt alleen bij hover | Zorg dat het ook opent met Enter of pijltjestoetsen |
| Alleen drag-and-drop | Werkt niet met toetsenbord | Voeg knoppen toe voor verplaatsen of sorteren |
Voorkom toetsenbordvallen
Een toetsenbordval ontstaat als je wel ergens naartoe kunt navigeren, maar er niet meer van weg kunt. Succescriterium 2.1.2 Geen toetsenbordval eist dat dit niet gebeurt. Zo’n toetsenbordval blokkeert de hele pagina voor toetsenbordgebruikers.
Dit criterium valt onder non-interferentie. Dat betekent dat het altijd moet worden voldaan, zelfs op delen van een pagina die geen volledige WCAG-conformiteit claimen. Eén toetsenbordval laat de hele pagina falen.
Zorg dat gebruikers altijd weg kunnen met Tab, Shift + Tab of pijltjestoetsen. Als een component een andere afsluitmethode gebruikt, informeer de gebruiker dan vóórdat het component focus krijgt.
Veelvoorkomende bronnen van toetsenbordvallen zijn:
- ingesloten social media widgets
- rich text editors die alle toetsaanslagen opvangen
- datumkiezers die focus oneindig door datums laten circuleren
- maatwerk componenten
Modals: focus opsluiten mag, mits je eruit kunt
De focus vasthouden in een modaal dialoogvenster is géén toetsenbordval. Bij een modal houd je de focus bewust vast binnen het venster. Dat voorkomt dat gebruikers achter het dialoogvenster terechtkomen in content die niet actief is. Maar bied altijd een toetsenbordtoegankelijke manier om het venster te sluiten, zoals de Escape-toets of een focusbare sluitknop. Ontbreekt die? Dan is het wél een toetsenbordval.
Let op: Zet na het sluiten van een modal de focus terug op het element dat de modal opende, anders verliest de toetsenbordgebruiker zijn positie op de pagina.
Het native <dialog>-element met showModal() biedt focus-trapping, Escape-ondersteuning. De achtergrondcontent wordt daarbij automatisch inactief gemaakt. Dat is de eenvoudigste manier om tegenwoordig een toegankelijke modal te bouwen. Het HTML inert-attribuut maakt achtergrondcontent niet-interactief en vervangt de oudere combinatie van aria-hidden="true" en tabindex="-1".
Gebruik modifiertoetsen voor sneltoetsen
Succescriterium 2.1.4 Enkel teken sneltoetsen gaat over sneltoetsen die alleen uit letters, cijfers, leestekens of symbolen bestaan. Deze kunnen per ongeluk activeren. Gebruikers van spraakherkenningssoftware dicteren woorden als reeksen letters. Eén gesproken woord kan dan meerdere ongewenste acties activeren.
Als je sneltoetsen met alleen afdruktekens gebruikt, zorg dan voor ten minste één van deze opties: een manier om sneltoetsen uit te schakelen, een manier om sneltoetsen aan te passen met niet-afdruktekens (zoals Ctrl of Alt), of zorg dat sneltoetsen alleen werken wanneer het onderdeel focus heeft.
Dit criterium geldt niet voor sneltoetsen die al een modifiertoets bevatten, native componenten waarbij lettertoetsen alleen werken bij focus (zoals type-ahead in een <select>), browsersneltoetsen of schermlezersneltoetsen.
Let op: Het gaat om afdruktekens, niet om het aantal fysieke toetsen dat je moet indrukken. Op de meeste toetsenborden typ je ? via Shift + /. Dat telt nog steeds als één afdrukteken. Een sneltoets die ? gebruikt valt dus onder dit criterium.
Houd de focusvolgorde logisch
Succescriterium 2.4.3 Focus volgorde eist dat de volgorde waarin componenten focus krijgen logisch is. De betekenis en bedienbaarheid van de content moet behouden blijven.
Logisch is niet hetzelfde als visueel
Een veelvoorkomend misverstand: de focusvolgorde hoeft niet identiek te zijn aan de visuele volgorde. Het W3C stelt expliciet dat de focusvolgorde niet de visuele layout hoeft te volgen. Er kunnen meerdere logische volgordes bestaan. In de praktijk betekent dit meestal: header eerst, dan de navigatie, dan de content en tot slot de footer. Pas de HTML-volgorde in de broncode aan om deze structuur te volgen.
Gebruik alleen deze tabindex-waarden:
| Waarde | Wanneer gebruiken |
|---|---|
tabindex="0" | Maak een niet-interactief element focusbaar |
tabindex="-1" | Haal element uit tabvolgorde, maar maak het programmatisch focusbaar via JavaScript |
Waarom geen positieve tabindex-waarden? Positieve waarden (tabindex="1", tabindex="2" enz.) overschrijven de DOM-volgorde. Elementen met een positieve tabindex krijgen altijd als eerste focus, vóór alle elementen zonder tabindex. Als je later een nieuw element toevoegt, belandt het aan het einde van de focusvolgorde. Het resultaat is een kwetsbaar systeem dat breekt bij elke wijziging.
Pas op met CSS die de visuele volgorde wijzigt. CSS-eigenschappen zoals flex-direction: row-reverse, order (Flexbox), grid-template-areas (Grid) en position: absolute veranderen de visuele volgorde, maar niet de DOM-volgorde. De focusvolgorde volgt de DOM. Dit leidt tot een verschil tussen wat de gebruiker ziet en waar het toetsenbord naartoe springt.
Verplaats focus bij dynamische content
Als er nieuwe content verschijnt (een dialoogvenster, foutmelding of uitklapmenu), verplaats dan de focus naar het relevante element in die nieuwe content. Als de content verdwijnt, zet de focus terug naar het element dat de actie heeft geopend. Doe je dit niet, dan moet een toetsenbordgebruiker door de hele pagina Tab-en om de nieuwe content te bereiken.
Geen onverwachte veranderingen bij focus
Succescriterium 3.2.1 Bij focus stelt dat er geen onverwachte veranderingen mogen plaatsvinden wanneer een element toetsenbordfocus krijgt. Denk aan een pop-up die opent of een formulier dat automatisch verstuurt zodra een element focus ontvangt. Toetsenbordgebruikers navigeren door de pagina door van element naar element te Tab-en. Als focus op een element al een actie triggert, kunnen zij de pagina niet verkennen zonder onbedoelde gevolgen.
Een verandering van content is niet automatisch een contextwijziging. Het dynamisch tonen van een helptekst naast een veld bij focus is geen probleem. Een contextwijziging is iets ingrijpenders: het openen van een nieuw venster, het verplaatsen van de focus naar een ander element, of het verzenden van een formulier.
Maak de toetsenbordfocus zichtbaar
Succescriterium 2.4.7 Focus zichtbaar eist dat elke component van de gebruikersinterface een duidelijke focusindicator heeft. Gebruikers moeten kunnen zien waar ze zijn.
Wat is een focusindicator?
Een focusindicator is de visuele markering die aangeeft welk element op dat moment toetsenbordfocus heeft. Browsers hebben een standaard focusindicator (meestal een blauwe of zwarte outline). Die voldoet voor dit criterium.
Verwijder de standaard-focusindicator niet
Zodra je de standaardindicator overschrijft (met outline: none of outline: 0), ben je als auteur verantwoordelijk voor een zichtbare vervanging. Geen vervanging toevoegen is de meest voorkomende fout.
Contrasteis voor focusindicatoren
Succescriterium 2.4.7 specificeert zelf geen minimumcontrast of minimumgrootte voor de focusindicator. Maar succescriterium 1.4.11 Contrast van niet-tekstuele content (niveau AA) vereist minstens 3:1 contrast voor focusindicatoren tegen aangrenzende kleuren.
Voorkom dat de focus wordt bedekt
Sticky headers, cookiebanners en chatwidgets zweven over de pagina-inhoud. Als een toetsenbordgebruiker naar een element tabt dat volledig achter zo’n laag verdwijnt, is niet meer te zien waar de focus is. Succescriterium 2.4.11 Focus niet bedekt (minimum) wil dit voorkomen.
Dit criterium eist dat een element met toetsenbordfocus niet volledig bedekt is door content die de auteur heeft gemaakt. Gedeeltelijk bedekken is op niveau AA toegestaan, maar vermijd dit zo veel mogelijk.
Let op: Het criterium kijkt naar het component zelf, niet naar de focusindicator. Steekt alleen de outline uit? Dan is het component alsnog volledig bedekt en faalt het.
Vereisten en aanbevelingen voor toegankelijke toetsenbordbediening
Dit zijn de vereisten en aanbevelingen voor toegankelijke toetsenbordbediening:
WCAG-vereisten
- Alle bedieningselementen zijn bereikbaar en bedienbaar met het toetsenbord.
- Bied alternatieven voor complexe gebaren, sleepbewegingen en bewegingsactivering.
- Toetsenbordgebruikers kunnen overal weer weg. Er zijn geen toetsenbordvallen.
- De focusvolgorde is logisch en bewaart betekenis en bedienbaarheid.
- De focusindicator is zichtbaar als een element toetsenbordfocus heeft.
- Elementen die de focus hebben zijn niet volledig bedekt door andere content.
- Enkel teken sneltoetsen kunnen worden uitgezet, opnieuw toegewezen, of zijn alleen actief bij focus.
- Er vinden geen onverwachte veranderingen plaats als een element focus krijgt.
Aanbevolen
- Volg de gebruikelijke toetsenbordconventies.
- Gebruik semantische HTML-elementen (
<button>,<a>,<input>) in plaats van<div>of<span>voor bedieningselementen. - Vermijd positieve tabindex-waarden. Gebruik alleen
tabindex="0"entabindex="-1".
Gerelateerde succescriteria
Dit artikel behandelt de volgende WCAG-succescriteria:
- 2.1.1 Toetsenbord (niveau A)
- 2.1.2 Geen toetsenbordval (niveau A)
- 2.1.4 Enkel teken sneltoetsen (niveau A)
- 2.4.3 Focus volgorde (niveau A)
- 2.4.7 Focus zichtbaar (niveau AA)
- 2.4.11 Focus niet bedekt (minimum) (niveau AA)
- 2.5.1 Aanwijzergebaren (niveau A)
- 2.5.4 Bewegingsactivering (niveau A)
- 2.5.7 Sleepbewegingen (niveau AA)
- 3.2.1 Bij focus (niveau A)