De wetgeving wijst op dit moment naar WCAG 2.1 AA. Maar dat is niet de nieuwste versie: WCAG 2.2 is al af sinds oktober 2023. De Europese norm EN 301 549, waar die wetgeving in de praktijk naar verwijst, schuift naar verwachting eind 2026 door naar WCAG 2.2.

WCAG 2.2 is geen nieuwe start. Vrijwel alles uit 2.1 geldt nog steeds: er komt een handvol criteria bij, er verdwijnt er één. Wat je al hebt opgelost, blijft opgelost.

Van 50 naar 55 verplichte criteria

Het aantal succescriteria per niveau.
Niveau WCAG 2.1 WCAG 2.2
A 30 31
AA 20 24
AAA 28 31

De niveaus stapelen: niveau AA betekent voldoen aan de criteria van niveau A én van niveau AA. Van de nieuwe criteria zitten er 6 op A of AA, de rest is AAA; het criterium dat verdwijnt zat op A. Onder de streep hou je dus 5 criteria méér over waar je aan moet voldoen.

Hieronder loop ik ze langs. De Engelse namen zet ik erbij, want die kom je tegen in auditrapporten en in de documentatie van het W3C.

De nieuwe criteria tot en met AA

2.4.11 Focus niet verborgen, minimum (Focus Not Obscured), AA

Krijgt een element focus met de tab-toets, dan mag het niet volledig schuilgaan achter iets wat jij op de pagina hebt gezet. Denk aan een header die bovenaan blijft plakken, een cookiebalk onderin, of een chatbubbel rechtsonder.

Dit is een criterium dat je alleen vindt door zelf te tabben. Een scanner ziet het niet, want volgens de code is het element gewoon zichtbaar. Er ligt alleen iets overheen.

Mijn eigen site had dit ook; omdat mijn header blijft staan, kon een gefocuste link eronder verdwijnen. Op mobiel laat ik de header nu meescrollen. En op desktop reserveer ik nu ruimte, zodat de browser verder scrollt dan het element zelf:

@media (min-width: 768px) {
:focus-visible {
scroll-margin-top: 5rem;
}
}

scroll-margin-top zegt hoeveel ruimte de browser boven het element vrij moet houden als hij er bij focus automatisch naartoe scrolt. Houd minstens de hoogte van je plakkende header aan.

2.5.7 Sleepbewegingen (Dragging Movements), AA

Alles wat je met slepen bedient, moet ook zonder slepen kunnen. Met één aanwijzer, dus met één klik of één tik.

Een kanbanbord waarop je kaartjes tussen kolommen sleept, heeft ook een menu "verplaats naar" nodig. Een prijsschuif heeft ook plus- en minknoppen nodig, of een invoerveld. Een kaart die je alleen met slepen kunt verschuiven, heeft ook pijlknoppen nodig.

Dat laatste bouwde ik onlangs in GravityView. In de View-editor sleep je velden tussen gebieden; daar zit nu een toolbar naast met pijlknoppen die hetzelfde doen met één klik.

In de GravityView-editor verplaatst een veld naar een ander gebied via de pijlknoppen in de toolbar, zonder te slepen. Video zonder geluid, 3 seconden.

Let op: dat het met het toetsenbord werkt is hier niet genoeg. Dit criterium gaat over mensen die wél een muis of touchscreen gebruiken, maar geen stabiele sleepbeweging kunnen maken. Door een tremor bijvoorbeeld, of omdat ze het scherm met een stok bedienen.

Uitzondering: als slepen de functie zelf is, zoals tekenen in een tekenprogramma.

2.5.8 Grootte van het doelgebied, minimum (Target Size), AA

Alles wat je aan kunt klikken is minstens 24 bij 24 CSS-pixels. Is het kleiner, dan moet er genoeg ruimte omheen liggen: een denkbeeldige cirkel met een doorsnede van 24 pixels, gecentreerd op het doel, mag geen ander doel raken en ook niet de cirkel van een ander te klein doel.

Waar het vaak misgaat: een rijtje social-icoontjes van 16 pixels tegen elkaar aan in de footer, een klein kruisje om een melding te sluiten, paginanummers onder een overzicht, actie-icoontjes in een tabelrij.

Uitzonderingen: een link midden in een lopende zin telt niet mee, en het geldt ook niet als dezelfde functie ergens anders op de pagina wel groot genoeg staat.

In mijn eigen header stond de taalwissel op 16 bij 16 pixels, terwijl het themaknopje ernaast 32 bij 32 was. Zelfde rij, zelfde icoongrootte, alleen zat er om die ene geen padding. De vlag is nog even groot; alleen het klikgebied eromheen is gegroeid:

a.language-toggle {
display: flex;
justify-content: center;
padding: 8px;
}

Niveau AAA vraagt al sinds 2.1 om 44 bij 44 pixels. Die 24 is de haalbare ondergrens die 2.2 daaronder legt.

3.2.6 Consistente hulp (Consistent Help), A

Bied je hulp aan, dan staat die op elke pagina op dezelfde plek in dezelfde volgorde. Een contactlink, een telefoonnummer, een chat, een link naar je veelgestelde vragen.

Dit criterium verplícht je trouwens niet om hulp aan te bieden. Doe je het wel, dan mag het niet verspringen. Fout gaat het als je contactgegevens op de homepage onderin de footer staan, maar in de checkout opeens weggestopt zitten in een hamburgermenu.

Het is de volgorde die telt, niet de exacte plek in pixels. Staat je contactlink op elke pagina als laatste in de footer, dan is dat prima, ook als die footer op de ene pagina langer is dan op de andere.

3.3.7 Overbodige invoer (Redundant Entry), A

Vraag binnen één proces niet twee keer om dezelfde informatie. De klassieker is een bestelling waarbij je eerst het bezorgadres invult en daarna het factuuradres nog een keer, zonder vinkje "zelfde als bezorgadres". Of een aanvraag in 4 stappen die in stap 3 nog eens om je e-mailadres vraagt.

Je lost het op door de informatie voor te vullen, of door de bezoeker te laten kiezen uit wat hij eerder al heeft ingevuld.

Uitzonderingen: als opnieuw invullen juist de bedoeling is, zoals bij het bevestigen van een wachtwoord of een beveiligingscontrole, en als de eerdere informatie niet meer geldig is.

3.3.8 Toegankelijke authenticatie, minimum (Accessible Authentication), AA

Inloggen mag geen geheugentest of puzzel zijn. In de praktijk gaat het om plakken en autocomplete.

Blokkeer plakken niet, niet in het wachtwoordveld en niet in het veld voor een eenmalige code. Dat wordt nog steeds gedaan "voor de veiligheid", en het sloopt precies de manier waarop veel mensen veilig inloggen.

En zet de autocomplete-attributen goed, zodat de browser en wachtwoordmanagers hun werk kunnen doen:

<input type="email" name="email" autocomplete="username">
<input type="password" name="password" autocomplete="current-password">
<input type="text" name="code" autocomplete="one-time-code" inputmode="numeric">

Een captcha waarbij je vervormde letters moet overtypen valt af. Een captcha van het type "klik alle stoplichten aan" mag technisch nog wel: objectherkenning is een uitzondering op dit criterium. Op niveau AAA vervalt die uitzondering.

Eén criterium verdwijnt: 4.1.1 Parsing

Dit ging over de techniek onder je HTML: geen dubbele id's, tags netjes openen en sluiten, geen dubbele attributen. In WCAG 2.2 is het geschrapt. Hulpsoftware leest je HTML niet meer zelf, maar krijgt hem via de browser; en die repareert dit soort fouten.

Maar let op! Twee elementen met dezelfde id breken nog steeds een aria-labelledby die daarnaar verwijst. Dat viel altijd al onder 1.3.1 of 4.1.2. Zelfde fout, ander criterium.

De nieuwe criteria op AAA

De rest zit op niveau AAA. Verplicht worden die niet, maar één ervan is de moeite waard.

  • 2.4.12 Focus niet verborgen, uitgebreid. Strenger dan 2.4.11: er mag geen enkel deel van het gefocuste element afgedekt zijn.
  • 2.4.13 Uiterlijk van focus. Je focusrand is minstens 2 pixels dik, loopt helemaal rond het element, en heeft 3:1 contrast met hoe het element er zonder focus uitziet. Dit is de moeite, want een duidelijke focusrand kost je niet meer werk dan een vage.
  • 3.3.9 Toegankelijke authenticatie, uitgebreid. Hier vervallen de uitzonderingen voor objectherkenning en persoonlijke content. Een captcha van het type "klik alle stoplichten aan" mag dan dus niet meer.

Wat betekent dit voor jou

Zit je nu op WCAG 2.1 niveau AA, dan is het gat naar WCAG 2.2 AA smal. Het meeste is frontend-werk van uren, geen weken. Alleen sleepalternatieven en overbodige invoer kunnen meer werk zijn, want daar zitten vaak functionele wijzigingen aan vast, niet alleen hoe het eruitziet.

Begin bij plakken toestaan en de autocomplete-attributen zetten. Dat is de kleinste moeite, en het raakt iedereen die inlogt.

Wil je weten wat er in jouw code moet gebeuren om hier te komen? Kijk dan bij website toegankelijk maken.