Voorbeeldrapportage — Dit rapport is gegenereerd op basis van een fictieve website (website.nl) en dient ter illustratie van hoe Joomill de toegankelijkheid van jouw website inventariseert. De cijfers en vindplaatsen zijn niet echt.
Joomill
Gegenereerd op 23 april 2026

Toegankelijkheidsrapport

Voorbeeldrapportage op basis van een fictieve website. Dit document toont hoe Joomill de toegankelijkheid van jouw website in kaart brengt: een volledige inventaris van alle 92 toegankelijkheidsregels die geautomatiseerd worden gecontroleerd, met per overtreding een gedetailleerd overzicht van vindplaatsen en oplossingsrichtingen.

Getest domein
website.nl
URL's gescand
47
Regels
92
Overtredingen
125

1. Managementsamenvatting

Deze samenvatting toont in één oogopslag hoe website.nl (fictief voorbeeld) scoort op de 92 geautomatiseerde toegankelijkheidsregels uit WCAG en aanverwante best practices. Let op: geautomatiseerde tests dekken circa 30 tot 40 procent van alle WCAG criteria af. Voor volledige conformiteit vult Joomill dit aan met handmatige controle.

82
Regels geslaagd
Geen overtredingen gevonden
10
Regels met overtredingen
Op één of meer pagina's
125
Totale overtredingen
Verspreid over 20 van de 47 URL's

Score per regelgroep

RegelgroepTotaalGeslaagdOvertredenMeldingen
Best Practice 28 25 3 12
WCAG 2.0 A 55 51 4 25
WCAG 2.0 AA 3 2 1 39
WCAG 2.0 AAA 3 2 1 45
WCAG 2.1 AA 2 2 0 0
WCAG 2.2 AA 1 0 1 4

2. Prioriteitenlijst

De meeste overtredingen op website.nl clusteren rond een beperkt aantal onderwerpen. Met afstand de grootste categorie is kleurcontrast: 84 van de 125 overtredingen (67%) komen uit de contrast-regels. Een gerichte aanpassing aan de kleurvariabelen lost het leeuwendeel van de issues op. De overige issues zijn individueler.

  1. Kleurcontrast volgens WCAG 2.0 AA oplossen

    Op 17 pagina's voldoet tekst niet aan het minimale contrast van 4.5:1 (3:1 voor grote tekst), 39 elementen in totaal. Dit is een harde eis voor WCAG 2.0 AA en daarmee voor de European Accessibility Act. Pak de CSS kleurvariabelen aan die body-, muted- en link-kleuren bepalen en test met een contrast checker.

  2. Formuliervelden van labels voorzien

    9 formuliervelden op 5 pagina's missen een gekoppeld label. Dit is een Critical impact issue: schermlezer-gebruikers kunnen de velden niet identificeren. Gebruik een zichtbaar <label> element met for-attribuut, of minimaal aria-label.

  3. AAA contrast als bonus meenemen

    De AAA regel (contrastratio 7:1) wordt op 45 plekken niet gehaald, verdeeld over 20 URL's. AAA is geen wettelijke eis, maar als je toch de AA contrasten aanpakt, is AAA vaak gratis meegenomen. Veel AAA overtredingen lossen vanzelf op als AA beter wordt.

  4. Heading-structuur corrigeren

    Op 10 pagina's klopt de heading-hiërarchie niet (h1 ontbreekt of niveaus worden overgeslagen). Dit raakt ook SEO want zoekmachines gebruiken heading-structuur om paginastructuur te begrijpen. Controleer de template elementen: zet de titel van de eerste sectie op h1 en bouw onderliggende koppen op in logische volgorde.

  5. Overige losse issues wegwerken

    Een reeks kleinere issues die meestal op individuele pagina's voorkomen: Images Require Alternate Text (6x), Links Require Discernible Text (8x), Select Element Requires Accessible Name (2x), Touch Targets Require Sufficient Size & Spacing (4x), Page Requires One Main Landmark (2x). Deze zijn meestal snel op te lossen en samen verbeteren ze de totale score aanzienlijk.

3. Volledig handboek (92 regels)

Alle 92 regels die geautomatiseerd worden gecontroleerd, gegroepeerd naar bron (Best Practice of WCAG versie). Per regel: uitleg van wat er gecontroleerd wordt, waarom het belangrijk is, hoe je het oplost, een code voorbeeld waar relevant, en hoe je verifieert. Voor overtreden regels volgt direct onderaan de kaart een gedetailleerd overzicht van aantal, vindplaatsen en specifieke aanpak.

Geslaagd — geen overtredingen
Moderate — kleine impact
Serious — merkbare impact
Critical — blokkeert het gebruik

Best Practice

25 van 28 regels geslaagd · 12 overtredingen

Unieke accesskey waarden

GeslaagdBest Practice
Wat controleert deze regel?

Het accesskey attribuut laat toe dat een gebruiker via een sneltoets direct naar een bepaald element springt. Als meerdere elementen dezelfde accesskey hebben werkt de sneltoets niet voorspelbaar.

Waarom is dit belangrijk?

Toetsenbord-gebruikers en schermlezer-gebruikers die op sneltoetsen vertrouwen raken in de war wanneer dezelfde toets naar verschillende plekken leidt. Bovendien kunnen accesskeys conflicteren met bestaande browser- of assistive-technology sneltoetsen.

Hoe los je dit op?

Gebruik accesskey zo min mogelijk. Als je ze toepast, zorg dat elke waarde binnen de pagina uniek is. Beter nog: vervang accesskeys door goede skip-links en logische tab-volgorde, want accesskey-gedrag is onvoorspelbaar op verschillende besturingssystemen en browsers.

Code voorbeeld
Fout
<a accesskey="h" href="/home">Home</a>
<a accesskey="h" href="/help">Help</a>
Correct
<a accesskey="h" href="/home">Home</a>
<a accesskey="p" href="/help">Help</a>
Hoe controleer je dit?

Doe een DOM-zoekopdracht op alle accesskey attributen en controleer op duplicaten. Herhaal daarna de toegankelijkheidstest.

Geen tabindex groter dan nul

GeslaagdBest Practice
Wat controleert deze regel?

Tabindex bepaalt in welke volgorde elementen focus krijgen bij tabben. Een positieve tabindex (1, 2, 3...) dwingt een custom volgorde af die afwijkt van de natuurlijke DOM-volgorde.

Waarom is dit belangrijk?

Een tabindex-waarde hoger dan 0 breekt de intuïtieve tab-volgorde. Schermlezer- en toetsenbord-gebruikers verwachten dat ze van boven naar beneden door de pagina tabben. Positieve waarden dwingen uitzonderingen af die bij elke paginawijziging opnieuw gehandhaafd moeten worden.

Hoe los je dit op?

Gebruik uitsluitend tabindex="0" (element wordt focusbaar op natuurlijke positie) of tabindex="-1" (element focusbaar via JavaScript, niet via tab). Verwijder alle positieve waarden en herorden de DOM als de volgorde niet klopt.

Code voorbeeld
Fout
<input tabindex="3" name="voornaam">
<input tabindex="1" name="email">
<input tabindex="2" name="bericht">
Correct
<input name="voornaam">
<input name="email">
<input name="bericht">
Hoe controleer je dit?

Doorloop de pagina met alleen de Tab-toets en controleer of de volgorde logisch aansluit bij de visuele layout.

ARIA dialog en alertdialog hebben toegankelijke naam nodig

GeslaagdBest Practice
Wat controleert deze regel?

Elementen met role="dialog" of role="alertdialog" (modals, popups) moeten een naam hebben zodat de schermlezer deze aankondigt bij het openen.

Waarom is dit belangrijk?

Zonder naam weet een gebruiker met een schermlezer niet waarover de dialog gaat. Een anoniem "dialog opened" is geen bruikbare aankondiging.

Hoe los je dit op?

Geef de dialog een aria-label (korte tekst) of aria-labelledby (verwijzing naar een bestaand heading element binnen de dialog).

Code voorbeeld
Fout
<div role="dialog">
  <p>Weet je zeker dat je wilt verwijderen?</p>
  <button>Ja</button>
  <button>Nee</button>
</div>
Correct
<div role="dialog" aria-labelledby="dlg-title">
  <h2 id="dlg-title">Verwijderen bevestigen</h2>
  <p>Weet je zeker dat je wilt verwijderen?</p>
  <button>Ja</button>
  <button>Nee</button>
</div>
Hoe controleer je dit?

Open de dialog met een schermlezer en luister of de titel wordt voorgelezen bij het openen.

ARIA treeitem knopen hebben toegankelijke naam nodig

GeslaagdBest Practice
Wat controleert deze regel?

Items binnen een tree widget (hiërarchische boomstructuur, zoals een file explorer) moeten een duidelijke naam hebben.

Waarom is dit belangrijk?

Schermlezers navigeren door de boom en moeten elk item kunnen identificeren. Zonder naam hoort de gebruiker alleen "treeitem" zonder context.

Hoe los je dit op?

Zorg dat elk element met role="treeitem" tekstinhoud heeft, of gebruik aria-label of aria-labelledby.

Code voorbeeld
Correct
<ul role="tree">
  <li role="treeitem" aria-expanded="true">Documenten
    <ul role="group">
      <li role="treeitem">2024.pdf</li>
    </ul>
  </li>
</ul>
Hoe controleer je dit?

Navigeer met pijltjestoetsen door de boomstructuur en controleer of elk item voorgelezen wordt.

role=text zonder focusbare kinderen

GeslaagdBest Practice
Wat controleert deze regel?

role="text" wordt gebruikt om schermlezers te vertellen dat een samengesteld element als één tekstblok moet worden voorgelezen. Focusbare elementen binnen zo'n blok creëren een conflict.

Waarom is dit belangrijk?

Wanneer een link of knop binnen een role=text staat wordt die wel focusbaar maar niet als interactief element aangekondigd. De gebruiker kan er op tabben zonder te weten wat het is.

Hoe los je dit op?

Verwijder focusbare elementen uit blokken met role="text" of haal de role weg. Gebruik role="text" alleen op statische content zonder interactie.

Hoe controleer je dit?

Tab door de content: als focus landt op een element binnen role=text, is er een probleem.

Formulierelementen hebben zichtbaar label nodig

GeslaagdBest Practice
Wat controleert deze regel?

Ieder formulierveld hoort een visueel zichtbaar label te hebben. Placeholders of aria-labels alleen zijn niet voldoende.

Waarom is dit belangrijk?

Zichtbare labels helpen alle gebruikers: mensen met cognitieve beperkingen herkennen het veld als ze typen, mensen met dyscalculie of geheugenproblemen hoeven niet te onthouden wat een placeholder zei nadat ze begonnen te typen, en het helpt browser-autofill correct te functioneren.

Hoe los je dit op?

Plaats een <label> element zichtbaar bij elk formulierveld. Placeholder-tekst is een aanvulling, geen vervanging.

Code voorbeeld
Fout
<input type="email" placeholder="E-mailadres">
Correct
<label for="email">E-mailadres</label>
<input type="email" id="email" placeholder="jij@voorbeeld.nl">
Hoe controleer je dit?

Controleer op elke pagina met formulieren of bij ieder invulveld een zichtbaar tekstlabel staat.

Frames moeten toegankelijkheidstest ondergaan

GeslaagdBest Practice
Wat controleert deze regel?

Als een pagina <iframe> of <frame> bevat, moet de toegankelijkheidscontrole ook binnen die frames worden uitgevoerd. Anders blijft de inhoud van de frame ongecontroleerd.

Waarom is dit belangrijk?

Iframes bevatten vaak externe content (embeds, formulieren, video's) die ook toegankelijk moet zijn. Zonder test in de iframe kunnen grote problemen onopgemerkt blijven.

Hoe los je dit op?

Zorg dat de toegankelijkheidscontrole ook binnen iframes wordt uitgevoerd. Voor productie: controleer dat externe embeds (YouTube, Google Maps, formulieren van derden) zelf toegankelijk zijn.

Hoe controleer je dit?

Voor externe iframes: test de ingebedde URL apart. Voor eigen iframes: zorg dat een toegankelijkheidschecker ook binnen de frame draait.

Correct gebruik van scope attribuut in tabellen

GeslaagdBest Practice
Wat controleert deze regel?

Het scope attribuut op <th> elementen geeft aan of de header voor een rij (scope="row") of kolom (scope="col") geldt. Andere waarden zijn colgroup of rowgroup.

Waarom is dit belangrijk?

Schermlezers gebruiken scope om bij het voorlezen van een cel te weten welke header erbij hoort. Verkeerde of ontbrekende scope maakt grote tabellen onbegrijpelijk.

Hoe los je dit op?

Gebruik alleen de waarden row, col, rowgroup of colgroup op <th>. Typische fout is scope op een <td> plaatsen, dat werkt niet.

Code voorbeeld
Fout
<tr><td scope="col">Maand</td><td scope="col">Totaal</td></tr>
Correct
<tr><th scope="col">Maand</th><th scope="col">Totaal</th></tr>
Hoe controleer je dit?

Navigeer met een schermlezer door een tabel en controleer of headers correct worden aangekondigd bij elke cel.

Alle pagina-inhoud binnen landmarks

GeslaagdBest Practice
Wat controleert deze regel?

Alle zichtbare content op een pagina hoort binnen een semantisch landmark te staan: <header>, <nav>, <main>, <aside> of <footer> (of de equivalente ARIA rollen).

Waarom is dit belangrijk?

Schermlezer-gebruikers navigeren door landmarks heen om snel bij een bepaalde sectie te komen. Content buiten landmarks wordt overgeslagen bij deze navigatie en is moeilijker te vinden.

Hoe los je dit op?

Wikkel alle content in de juiste HTML5 landmark-elementen. Losse <div>'s op top niveau horen hoogstwaarschijnlijk in een van de bovenstaande elementen thuis.

Code voorbeeld
Fout
<body>
  <div class="header">...</div>
  <div class="content">...</div>
  <div class="footer">...</div>
</body>
Correct
<body>
  <header>...</header>
  <main>...</main>
  <footer>...</footer>
</body>
Hoe controleer je dit?

Gebruik een browser-extensie zoals Landmarks (Firefox/Chrome) om alle landmarks op een pagina te visualiseren en controleer of er content tussen valt.

Pagina vereist een main landmark

ModerateBest Practice2x op 2 URLs
Wat controleert deze regel?

Elke pagina hoort precies één <main> element (of role="main") te hebben dat de hoofdinhoud omsluit.

Waarom is dit belangrijk?

Schermlezers bieden een sneltoets om direct naar de hoofdinhoud te springen. Zonder main landmark moet de gebruiker handmatig door de header en navigatie heen.

Hoe los je dit op?

Wikkel de unieke hoofdinhoud van de pagina (niet de gedeelde header, nav of footer) in een <main> element.

Code voorbeeld
Correct
<body>
  <header>...</header>
  <main>
    <h1>Paginatitel</h1>
    <!-- unieke inhoud -->
  </main>
  <footer>...</footer>
</body>
Hoe controleer je dit?

Zoek met DevTools naar <main> elementen: je hoort er precies één per pagina te vinden.

Overtredingen op deze site 2
Impact
Moderate
Prioriteit
Medium
Richtlijn
Best Practice
Beschrijving
Page must have one main landmark.
Standaard advies
Ensure the page has a main landmark (a main element or element with role="main").
Toon alle 2 vindplaatsen (2 unieke URLs)
URLLocatie op pagina (CSS selector)
https://www.website.nl/privacyhtml > body
https://www.website.nl/voorwaardenhtml > body

Niet meer dan één banner landmark

GeslaagdBest Practice
Wat controleert deze regel?

Per pagina mag er slechts één banner landmark zijn. Dit is normaal het <header> element dat direct kind is van <body>, of een element met role="banner".

Waarom is dit belangrijk?

Meerdere banners maken de paginastructuur onduidelijk. Schermlezer-gebruikers verwachten één herkenbare site-header waarin meestal logo en hoofdnavigatie staan.

Hoe los je dit op?

Gebruik <header> alleen op top niveau voor de site-header. Headers binnen <article> of <section> tellen niet als banner (dat zijn sectie-headers) mits ze binnen die elementen staan.

Hoe controleer je dit?

Zoek in DevTools of via een landmarks-extensie naar alle banner landmarks: je hoort er maximaal één te vinden.

Banner landmark niet binnen ander landmark

GeslaagdBest Practice
Wat controleert deze regel?

Een banner (site-header) hoort op het hoogste niveau van de pagina te staan, niet genest binnen een ander landmark.

Waarom is dit belangrijk?

Geneste banners doorbreken de verwachte hiërarchie. De gebruiker verwacht de banner als eerste te vinden met een sneltoets.

Hoe los je dit op?

Plaats <header> (met role="banner") als directe kind van <body>. Gebruik <header> binnen <article> of <section> alleen als sectie-header zonder role="banner".

Hoe controleer je dit?

Inspecteer DOM: de site-header moet een direct child zijn van body, niet van main, article of iets anders.

Niet meerdere contentinfo landmarks

GeslaagdBest Practice
Wat controleert deze regel?

Er hoort maximaal één contentinfo (footer) landmark per pagina te zijn. Dit is normaal de site-footer onderin.

Waarom is dit belangrijk?

Meerdere footers verwarren gebruikers die met footer-sneltoetsen naar copyright en contactinformatie springen.

Hoe los je dit op?

Gebruik <footer> op top niveau voor de site-footer. Footers binnen <article> (bijvoorbeeld een datum of auteursregel) tellen niet als contentinfo mits ze binnen het article element staan.

Hoe controleer je dit?

Inspecteer DOM: op top niveau hoort één <footer> of element met role="contentinfo" te staan.

Maximaal één main landmark

GeslaagdBest Practice
Wat controleert deze regel?

Een pagina mag maximaal één zichtbare main hebben. Meerdere mains zijn alleen toegestaan als er steeds één zichtbaar is (bijvoorbeeld bij tabbed interfaces).

Waarom is dit belangrijk?

Een uniek main landmark stelt gebruikers in staat direct naar de hoofdinhoud te springen. Meerdere mains ondermijnen die functionaliteit.

Hoe los je dit op?

Combineer de content in één main element, of verberg de niet-actieve mains met hidden attribuut.

Hoe controleer je dit?

Inspecteer DOM op meerdere main elementen en controleer of slechts één zichtbaar is.

Complementary landmarks op top niveau

GeslaagdBest Practice
Wat controleert deze regel?

Elementen met role="complementary" of <aside> op top niveau (niet binnen article of section) horen niet genest te zijn binnen andere landmarks.

Waarom is dit belangrijk?

Complementary landmarks (sidebars, aanverwante info) zijn ontworpen om naast de hoofdcontent te staan. Als ze genest worden binnen main of andere landmarks ontstaat een structureel onjuiste opbouw.

Hoe los je dit op?

Plaats <aside> die een zelfstandige sectie vertegenwoordigt als direct kind van <body>, naast <main>. Asides binnen <article> zijn anders en krijgen geen complementary rol toegewezen.

Hoe controleer je dit?

Inspecteer DOM: top-level asides moeten parallel aan main staan, niet erin.

Contentinfo landmark op top niveau

GeslaagdBest Practice
Wat controleert deze regel?

De site-footer (contentinfo landmark) hoort op het hoogste niveau van de pagina te staan.

Waarom is dit belangrijk?

Schermlezer-gebruikers springen met een sneltoets naar de footer voor contactinformatie. Een geneste footer is niet bereikbaar via die shortcut.

Hoe los je dit op?

Plaats <footer> met role="contentinfo" als direct kind van <body>. Als je <footer> binnen <main> of <article> gebruikt, gaat dat alleen op als het een sectie-specifieke footer is zonder role="contentinfo".

Hoe controleer je dit?

De site-footer moet in DevTools een direct child van body zijn.

Main landmark niet binnen ander landmark

GeslaagdBest Practice
Wat controleert deze regel?

Het <main> element mag niet genest zijn binnen een ander landmark (header, nav, aside, footer).

Waarom is dit belangrijk?

Main is per definitie de hoofdinhoud van de pagina en hoort parallel aan de andere landmarks te staan, niet eronder.

Hoe los je dit op?

Plaats <main> als direct kind van <body>, nooit binnen andere landmarks.

Hoe controleer je dit?

Inspecteer DOM: main hoort direct onder body te staan.

Landmarks met unieke rol of naam

GeslaagdBest Practice
Wat controleert deze regel?

Als een pagina meerdere landmarks van hetzelfde type heeft (bijvoorbeeld twee nav landmarks), moet elk een unieke naam hebben via aria-label of aria-labelledby.

Waarom is dit belangrijk?

Schermlezer-gebruikers zien bij een landmarks-lijst alleen het type van het landmark ("navigation"). Zonder onderscheidende naam kunnen ze "hoofdmenu" niet van "footer-menu" onderscheiden.

Hoe los je dit op?

Geef elke navigatie, section of complementary landmark een aria-label met een onderscheidende naam.

Code voorbeeld
Correct
<nav aria-label="Hoofdnavigatie">...</nav>
<nav aria-label="Footer">...</nav>
Hoe controleer je dit?

Open de landmarks-lijst in een schermlezer (bijvoorbeeld VoiceOver Rotor) en controleer dat elke landmark een unieke naam heeft.

Pagina bevat een <h1>

SeriousBest Practice3x op 3 URLs
Wat controleert deze regel?

Elke pagina hoort minstens één <h1> te bevatten die de hoofdtitel van de pagina weergeeft.

Waarom is dit belangrijk?

De h1 is het belangrijkste anker voor schermlezer-gebruikers: met de sneltoets "1" springen ze direct naar de paginatitel. Ook SEO hangt deels op een duidelijke h1. Zonder h1 mist de pagina een belangrijk oriëntatiepunt.

Hoe los je dit op?

Zorg dat elke pagina (ook subpagina's, blogposts en dynamisch gegenereerde pagina's) precies één h1 heeft die de hoofdonderwerpen van de pagina beschrijft. De sitenaam hoort daar meestal niet in.

Code voorbeeld
Correct
<main>
  <h1>Webshop laten maken in Waalwijk</h1>
  <h2>Wat krijg je van ons?</h2>
</main>
Hoe controleer je dit?

In DevTools: document.querySelectorAll('h1').length - dit hoort precies 1 te zijn. Doe dit op elke pagina-template, niet alleen de homepage.

Overtredingen op deze site 3
Impact
Serious
Prioriteit
Medium
Richtlijn
Best Practice
Beschrijving
Page should contain a level-one heading.
Standaard advies
Ensure the page, or at least one of its frames contains a level-one heading.
Toon alle 3 vindplaatsen (3 unieke URLs)
URLLocatie op pagina (CSS selector)
https://www.website.nl/nieuwsbriefhtml > body > main
https://www.website.nl/privacyhtml > body > main
https://www.website.nl/voorwaardenhtml > body > main

Heading levels alleen oplopend met één

SeriousBest Practice7x op 7 URLs
Wat controleert deze regel?

Heading niveaus mogen niet overslaan. Na h2 komt h3, niet direct h4. Bij terugschakelen mag wel van h3 naar h2.

Waarom is dit belangrijk?

Schermlezer-gebruikers vormen een mentaal beeld van de paginastructuur op basis van heading-niveaus. Een overgeslagen niveau suggereert een ontbrekende sectie en doorbreekt de hiërarchie.

Hoe los je dit op?

Controleer de heading-hiërarchie pagina voor pagina. Bij componenten (cards, widgets) vaak het probleem: een card bevat een h3 binnen een sectie met alleen h1, dus h2 ontbreekt. Oplossing is ofwel de card een h2 geven, ofwel een h2 sectiekop toevoegen.

Code voorbeeld
Fout
<h1>Diensten</h1>
<h3>Webdesign</h3>
<h3>SEO</h3>
Correct
<h1>Diensten</h1>
<h2>Webdesign</h2>
<h2>SEO</h2>
Hoe controleer je dit?

Installeer de HeadingsMap browser-extensie en controleer per pagina de hiërarchie. Let op templates die hetzelfde probleem veroorzaken op meerdere pagina's.

Overtredingen op deze site 7
Impact
Serious
Prioriteit
Medium
Richtlijn
Best Practice
Beschrijving
Heading levels should only increase by one.
Standaard advies
Ensure the heading hierarchy is logical and correctly represents the document structure.
Toon alle 7 vindplaatsen (7 unieke URLs)
URLLocatie op pagina (CSS selector)
https://www.website.nl/main > section:nth-child(3) > h4
https://www.website.nl/dienstenmain > section:nth-child(2) > h4
https://www.website.nl/casesmain > section.filter-bar > h4
https://www.website.nl/cases/gemeente-amersfoortarticle > div.content > h4
https://www.website.nl/blogmain > div.blog-grid > article > h4
https://www.website.nl/blog/toegankelijkheid-in-2026article > h3
https://www.website.nl/blog/kleurcontrast-in-de-praktijkarticle > h3

Presentational gemarkeerde elementen worden genegeerd

GeslaagdBest Practice
Wat controleert deze regel?

Elementen met role="presentation" of role="none" worden door schermlezers genegeerd. Als zo'n element toch focus krijgt of betekenisvolle child elementen heeft, ontstaat een conflict.

Waarom is dit belangrijk?

Een element dat als presentational is gemarkeerd hoort geen semantische rol meer te hebben, maar soms raapt de browser alsnog interactieve children op, wat verwarrend is.

Hoe los je dit op?

Gebruik role="presentation" alleen op zuivere layout-tags (oude tabellen voor layout, decoratieve iconen). Plaats geen interactieve of semantische inhoud binnen presentational elementen.

Hoe controleer je dit?

Controleer met DevTools Accessibility panel of presentational elementen inderdaad geen naam of rol hebben.

ARIA rol past bij het element

GeslaagdBest Practice
Wat controleert deze regel?

ARIA rollen mogen niet conflicteren met de semantiek van het onderliggende HTML element. role="button" op een <a> element wordt bijvoorbeeld afgeraden.

Waarom is dit belangrijk?

Dubbele of conflicterende semantiek verwart schermlezers. Gebruik de juiste HTML elementen in plaats van alles via ARIA op te lossen.

Hoe los je dit op?

Volg de regel "No ARIA is better than bad ARIA": gebruik <button> voor knoppen, <a href> voor links, <input type="checkbox"> voor checkboxes. Voeg ARIA alleen toe als het standaard HTML niet volstaat.

Code voorbeeld
Fout
<div role="button" tabindex="0">Klik hier</div>
Correct
<button>Klik hier</button>
Hoe controleer je dit?

Controleer of ieder element met een ARIA role echt die aanvullende informatie nodig heeft. Zo niet, gebruik het juiste HTML element.

Headings mogen niet leeg zijn

GeslaagdBest Practice
Wat controleert deze regel?

Heading-elementen (h1 tot h6) moeten altijd tekstinhoud of een equivalent voor schermlezers bevatten.

Waarom is dit belangrijk?

Lege headings creëren geen bruikbaar ankerpunt en verstoren de hiërarchie. Schermlezer-gebruikers zien een lege entry in de headings-lijst, wat verwarring veroorzaakt.

Hoe los je dit op?

Zorg dat elke heading tekst bevat. Als een heading een icoon is, gebruik dan een aria-label. Verwijder lege h-tags die vaak per ongeluk door CMS-editors worden toegevoegd.

Code voorbeeld
Fout
<h2></h2>
<h2><i class="icon-star"></i></h2>
Correct
<h2>Voordelen</h2>
<h2><i class="icon-star" aria-hidden="true"></i> Voordelen</h2>
Hoe controleer je dit?

DevTools console: Array.from(document.querySelectorAll('h1,h2,h3,h4,h5,h6')).filter(h => !h.textContent.trim()).length - hoort 0 te zijn.

Viewport staat inzoomen tot 500% toe

GeslaagdBest Practice
Wat controleert deze regel?

De meta viewport tag hoort gebruikers niet te beperken in inzoomen. Idealiter tot minimaal 500% voor mensen die dit nodig hebben om tekst te kunnen lezen.

Waarom is dit belangrijk?

Mensen met een visuele beperking hebben vaak 200 tot 500% zoom nodig. Als de viewport dit blokkeert of de maximum-scale te laag zet, is de site onbruikbaar voor hen.

Hoe los je dit op?

Gebruik een viewport tag zonder user-scalable=no en zonder maximum-scale, of zet maximum-scale op 5 of hoger.

Code voorbeeld
Fout
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
Correct
<meta name="viewport" content="width=device-width, initial-scale=1">
Hoe controleer je dit?

Test op mobiel: probeer te pinch-zoomen op de pagina. Als dit niet werkt, klopt de viewport niet.

Alt-tekst niet herhalen als zichtbare tekst

GeslaagdBest Practice
Wat controleert deze regel?

Als een afbeelding alt-tekst heeft die identiek is aan direct omringende zichtbare tekst, krijgt de schermlezer-gebruiker dezelfde informatie twee keer te horen.

Waarom is dit belangrijk?

Dubbele aankondigingen zijn vermoeiend en traag voor schermlezer-gebruikers. Ze zijn vaak het resultaat van automatisch gegenereerde alt-tekst in CMSen.

Hoe los je dit op?

Als de afbeelding puur decoratief is naast tekst met dezelfde betekenis, geef het een lege alt (alt=""). Geef het alleen een alt als het écht informatie toevoegt.

Code voorbeeld
Fout
<img src="award.png" alt="Award winnaar 2024">
<p>Award winnaar 2024</p>
Correct
<img src="award.png" alt="">
<p>Award winnaar 2024</p>
Hoe controleer je dit?

Loop door content-pagina's en check of img alt attributen niet identiek zijn aan de direct omringende tekst.

Tabelkoppen met duidelijke tekst

GeslaagdBest Practice
Wat controleert deze regel?

Elke <th> in een datatabel hoort leesbare tekst te bevatten die de inhoud van die kolom of rij beschrijft.

Waarom is dit belangrijk?

Schermlezers lezen bij elke cel de bijbehorende header voor. Lege of ondoorgrondelijke headers maken de tabel onleesbaar.

Hoe los je dit op?

Geef iedere th een duidelijke tekst. Gebruik aria-label als alleen een icoon in de header staat. Voorkom lege cellen links bovenin tabellen.

Hoe controleer je dit?

Controleer datatabellen in DevTools: elke th moet niet-lege tekstinhoud hebben.

Summary en caption niet identiek

GeslaagdBest Practice
Wat controleert deze regel?

Het summary attribuut en de <caption> van een tabel hebben verschillende functies en mogen niet dezelfde tekst bevatten.

Waarom is dit belangrijk?

Caption beschrijft wat de tabel is (titel), summary beschrijft de structuur en hoe de tabel gelezen moet worden. Als ze identiek zijn wordt de gebruiker tweemaal hetzelfde voorgelezen.

Hoe los je dit op?

Het summary attribuut is in HTML5 deprecated. Gebruik alleen <caption> voor de tabeltitel en leg de structuur uit in tekst boven de tabel indien nodig.

Hoe controleer je dit?

Verwijder summary attributen bij voorkeur geheel. Als ze er staan, moeten ze iets wezenlijk anders zeggen dan de caption.

WCAG 2.0 A

51 van 55 regels geslaagd · 25 overtredingen

Scrollbare regio moet toetsenbord-toegankelijk zijn

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Regios met overflow scroll (bijvoorbeeld een div met overflow-y:auto) moeten met toetsenbord te scrollen zijn. Dit vereist dat het element focusbaar is.

Waarom is dit belangrijk?

Gebruikers die geen muis gebruiken moeten ook de inhoud van scroll-containers kunnen lezen. Als het element geen focus krijgt, is er geen manier om te scrollen.

Hoe los je dit op?

Geef scrollbare containers tabindex="0" zodat ze focusbaar worden. De browser zorgt dan voor toetsenbord-scrollen met pijltjestoetsen en Page Up/Down.

Code voorbeeld
Fout
<div style="overflow-y:auto; height:200px">...lange content...</div>
Correct
<div tabindex="0" role="region" aria-label="Beschrijving" style="overflow-y:auto; height:200px">...lange content...</div>
Hoe controleer je dit?

Tab naar de scroll-container: je moet een focus-indicator zien. Gebruik dan pijltjestoetsen om te scrollen.

Vereiste ARIA attributen aanwezig

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Sommige ARIA rollen vereisen specifieke attributen om correct te functioneren. role="checkbox" vereist bijvoorbeeld aria-checked.

Waarom is dit belangrijk?

Zonder de verplichte attributen kan de schermlezer de staat van het element niet bepalen. Een checkbox zonder aria-checked klinkt bijvoorbeeld niet als checked of unchecked.

Hoe los je dit op?

Controleer per gebruikte ARIA rol welke attributen verplicht zijn. Gebruik bij voorkeur native HTML (input type=checkbox) waar dat mogelijk is.

Code voorbeeld
Fout
<div role="checkbox">Ik ga akkoord</div>
Correct
<div role="checkbox" aria-checked="false" tabindex="0">Ik ga akkoord</div>
Hoe controleer je dit?

Raadpleeg de ARIA Authoring Practices Guide voor elk role. Test met een schermlezer of staten correct worden aangekondigd.

ARIA attributen correct gebruiken per rol

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Elk ARIA attribuut heeft regels over welke rollen en elementen het mag gebruiken. Verkeerd gebruik maakt het attribuut ineffectief.

Waarom is dit belangrijk?

Een aria-checked op iets anders dan een checkbox- of radio-achtig element wordt door schermlezers genegeerd, maar kan wel verwarring veroorzaken of onverwacht gedrag geven.

Hoe los je dit op?

Gebruik aria-* attributen alleen op de rollen waarvoor ze bedoeld zijn. Raadpleeg WAI-ARIA 1.2 specificatie bij twijfel.

Hoe controleer je dit?

Automatische toegankelijkheidstools vangen dit op. Handmatig: vergelijk elk ARIA attribuut met de specificatie.

ARIA attributen met geldige waarden

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

ARIA attributen hebben vaak een beperkte set toegestane waarden. aria-expanded kan bijvoorbeeld alleen "true" of "false" zijn.

Waarom is dit belangrijk?

Een ongeldige waarde wordt genegeerd, waardoor de schermlezer de staat van het element niet kent. Dat maakt bijvoorbeeld collapsible menu's stuk voor schermlezer-gebruikers.

Hoe los je dit op?

Gebruik alleen de waarden uit de ARIA specificatie. Let op typefouten (TRUE in hoofdletters werkt wel, maar waarden als "yes" of "open" niet).

Code voorbeeld
Fout
<button aria-expanded="open">Menu</button>
Correct
<button aria-expanded="true">Menu</button>
Hoe controleer je dit?

Test in axe DevTools browser-extensie. Alle aria-* attributen met ongeldige waarden worden gerapporteerd.

ARIA attributen met geldige namen

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Alleen ARIA attributen die in de specificatie staan werken. Aria-exapnded (typo) of aria-foo (verzonnen) worden genegeerd.

Waarom is dit belangrijk?

Typo's in attribuutnamen zijn stille fouten: er gebeurt niets verkeerd zichtbaar, maar de beoogde toegankelijkheidsverbetering werkt niet.

Hoe los je dit op?

Gebruik de lijst van geldige ARIA attributen uit de WAI-ARIA specificatie. Moderne IDE's met HTML-linting vangen vaak typo's.

Hoe controleer je dit?

axe DevTools rapporteert onbekende aria-* attributen.

ARIA commands met toegankelijke naam

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Elementen met command-achtige rollen (role="button", role="link", role="menuitem") hebben een toegankelijke naam nodig.

Waarom is dit belangrijk?

Zonder naam wordt de knop aangekondigd als "button" zonder dat de gebruiker weet wat de actie doet. Dit maakt de knop effectief onbruikbaar voor schermlezer-gebruikers.

Hoe los je dit op?

Zorg dat de knop tekst bevat, of gebruik aria-label of aria-labelledby. Liever nog: gebruik een native <button> met tekst.

Code voorbeeld
Correct
<div role="button" aria-label="Sluiten" tabindex="0">×</div>
Hoe controleer je dit?

Tab naar elk command element en luister naar de aankondiging in een schermlezer.

ARIA input velden met toegankelijke naam

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Custom input componenten (role="textbox", role="combobox", role="searchbox") moeten een toegankelijke naam hebben.

Waarom is dit belangrijk?

Schermlezer-gebruikers moeten weten wat ze invullen. "textbox" zonder context is onbruikbaar.

Hoe los je dit op?

Gebruik aria-label, aria-labelledby, of een gekoppeld <label> element. Nog beter: gebruik native <input>.

Code voorbeeld
Correct
<div role="combobox" aria-label="Land" aria-expanded="false">...</div>
Hoe controleer je dit?

Tab naar elk ARIA input veld en controleer dat de naam wordt voorgelezen.

ARIA meter nodes met toegankelijke naam

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Elementen met role="meter" (voor bijvoorbeeld schijfruimte of batterijstatus) hebben een naam nodig die aangeeft wat er gemeten wordt.

Waarom is dit belangrijk?

Een meter zonder naam vertelt de gebruiker niet wat er gemeten wordt. Een waarde van 60% is betekenisloos zonder context.

Hoe los je dit op?

Gebruik bij voorkeur het native <meter> element met een zichtbaar label, of aria-label/aria-labelledby op een div met role=meter.

Code voorbeeld
Correct
<label for="disk">Schijfruimte</label>
<meter id="disk" value="0.6" min="0" max="1">60%</meter>
Hoe controleer je dit?

Raadpleeg DevTools Accessibility panel om de naam van de meter te controleren.

ARIA progressbar met toegankelijke naam

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Progressbars (role="progressbar") moeten een naam hebben die aangeeft wat er voortgaat.

Waarom is dit belangrijk?

"75% voltooid" is betekenisloos zonder context. De gebruiker moet weten of het om bestandsupload, pagina-laden of iets anders gaat.

Hoe los je dit op?

Gebruik native <progress> met label, of aria-label op een custom progressbar.

Code voorbeeld
Correct
<div role="progressbar" aria-label="Upload voortgang" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100">75%</div>
Hoe controleer je dit?

Schermlezer moet iets als "Upload voortgang, 75 procent" aankondigen.

ARIA rollen binnen vereiste ouder

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Sommige ARIA rollen mogen alleen binnen een specifieke ouder voorkomen. role="listitem" moet bijvoorbeeld binnen role="list" of een <ul>/<ol> staan.

Waarom is dit belangrijk?

Schermlezer-gebruikers verwachten bepaalde relaties. Een listitem zonder list is een weesitem zonder context.

Hoe los je dit op?

Gebruik ARIA rollen in de context waarvoor ze bedoeld zijn. Gebruik bij voorkeur native HTML (<ul><li>) zodat deze relatie automatisch klopt.

Hoe controleer je dit?

axe DevTools rapporteert weesrollen. Handmatig: controleer dat elke listitem, menuitem, treeitem een juiste parent heeft.

ARIA rollen met geldige waarden

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Alleen bestaande, juist gespelde ARIA rollen werken. role="buton" (typefout) of role="bigbutton" worden genegeerd.

Waarom is dit belangrijk?

Typfouten zijn stille fouten: de intentie is goed maar het effect is nul. De schermlezer krijgt geen rol-informatie door.

Hoe los je dit op?

Gebruik alleen rollen uit de WAI-ARIA specificatie. IDE's met HTML-linting vangen dit vaak op.

Hoe controleer je dit?

axe DevTools rapporteert onbekende role-waarden.

ARIA toggle velden met toegankelijke naam

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Toggle velden (checkbox, radio, switch) met ARIA rollen moeten een naam hebben zodat de gebruiker weet wat er aan of uit wordt gezet.

Waarom is dit belangrijk?

Een anonieme checkbox is niet te bedienen door schermlezer-gebruikers. "checked, checkbox" zonder label zegt niets.

Hoe los je dit op?

Geef elk toggle een label via <label>, aria-label of aria-labelledby. Gebruik bij voorkeur native inputs.

Code voorbeeld
Correct
<label><input type="checkbox"> Nieuwsbrief ontvangen</label>
Hoe controleer je dit?

Schermlezer moet bij elke toggle zowel de naam als de staat aankondigen.

ARIA tooltips met toegankelijke naam

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Elementen met role="tooltip" moeten een naam hebben, meestal de inhoud van de tooltip zelf.

Waarom is dit belangrijk?

Een naamloze tooltip wordt niet voorgelezen wanneer hij verschijnt, waardoor de hulpinfo niet toegankelijk is.

Hoe los je dit op?

Zorg dat de tooltip tekstinhoud heeft of gebruik aria-label. Koppel de tooltip aan het trigger-element met aria-describedby.

Code voorbeeld
Correct
<button aria-describedby="tip1">Info</button>
<div role="tooltip" id="tip1">Uitleg over deze knop</div>
Hoe controleer je dit?

Focus het trigger-element en controleer dat de tooltip-inhoud wordt voorgelezen.

Specifieke ARIA rollen vereisen bepaalde kinderen

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Rollen als role="list" vereisen role="listitem" als kinderen. role="menu" vereist role="menuitem". Ontbrekende kinderen maken de structuur onbruikbaar.

Waarom is dit belangrijk?

Als een menu geen menuitems bevat, navigeert de gebruiker door lucht. De schermlezer verwacht bepaalde structuur bij bepaalde rollen.

Hoe los je dit op?

Gebruik native HTML elementen die de correcte kind-elementen afdwingen. Bij custom widgets: zorg dat alle vereiste kindrollen aanwezig zijn.

Hoe controleer je dit?

Tab door de widget met een schermlezer en controleer of de structuur logisch is.

aria-braille vereist niet-braille variant

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

De attributen aria-braillelabel en aria-brailleroledescription mogen alleen gebruikt worden als er ook een gewone aria-label of aria-roledescription aanwezig is.

Waarom is dit belangrijk?

Braille-attributen zijn bedoeld als aanvulling op gesproken tekst, niet als vervanging. Zonder niet-braille variant mist de gesproken schermlezer informatie.

Hoe los je dit op?

Als je aria-braillelabel gebruikt, voeg dan altijd ook aria-label toe. Hetzelfde voor aria-brailleroledescription naast aria-roledescription.

Hoe controleer je dit?

Zoek in DOM naar aria-braille* attributen en controleer of er een niet-braille variant bij staat.

aria-hidden bevat geen focusbare elementen

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Als je een element verbergt voor schermlezers via aria-hidden="true", mag dat element geen focusbare elementen bevatten.

Waarom is dit belangrijk?

Tab naar een knop binnen aria-hidden geeft een paradox: de knop krijgt focus, maar de schermlezer meldt niets. De gebruiker raakt gedesoriënteerd.

Hoe los je dit op?

Als je een container verbergt, zorg dan dat geen enkel element erbinnen focusbaar is. Gebruik eventueel ook het hidden attribuut, of verwijder tabindex, of zet tabindex="-1" op focusbare kinderen.

Code voorbeeld
Fout
<div aria-hidden="true">
  <a href="/x">Klik hier</a>
</div>
Correct
<div aria-hidden="true" inert>
  <a href="/x">Klik hier</a>
</div>
Hoe controleer je dit?

Tab door de pagina en controleer of focus nooit in een aria-hidden container terechtkomt.

aria-hidden=true niet op <body>

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Het body element mag nooit aria-hidden="true" krijgen, aangezien dat de hele pagina verbergt voor schermlezers.

Waarom is dit belangrijk?

Een aria-hidden op body maakt de pagina compleet onzichtbaar voor schermlezer-gebruikers. De hele site wordt onbruikbaar.

Hoe los je dit op?

Verwijder aria-hidden="true" van het body element. Als je een modal opent en de rest wilt uitschakelen, gebruik dan inert of aria-hidden op een wrapper-div binnen body, niet op body zelf.

Hoe controleer je dit?

Inspecteer het body element: er mag geen aria-hidden op staan.

Elementen gebruiken alleen toegestane ARIA

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Bepaalde HTML elementen staan geen of beperkte ARIA toe. Een <div> mag alles, maar een <input type="submit"> mag geen aria-pressed.

Waarom is dit belangrijk?

Niet-toegestane ARIA op native elementen kan het gedrag verstoren. De browser en assistive technology raken in conflict.

Hoe los je dit op?

Volg de regel "No ARIA is better than bad ARIA". Controleer per element welke ARIA attributen zijn toegestaan in de HTML Accessibility API Mappings specificatie.

Hoe controleer je dit?

axe DevTools markeert niet-toegestane combinaties.

Elementen met toegestane ARIA attributen

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

ARIA attributen moeten passen bij de rol van het element, impliciet of expliciet. aria-checked op een <div> zonder role="checkbox" wordt genegeerd.

Waarom is dit belangrijk?

Attributen zonder passende rol hebben geen effect en suggereren vals veiligheid. De ontwikkelaar denkt dat iets toegankelijk is, maar het werkt niet.

Hoe los je dit op?

Gebruik ARIA attributen alleen in combinatie met de bijbehorende rol. Controleer per attribuut welke rollen het ondersteunen.

Hoe controleer je dit?

axe DevTools rapporteert dit soort mismatches.

ID's in ARIA en labels zijn uniek

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

ID's waar aria-labelledby, aria-describedby, for of andere attributen naar verwijzen moeten uniek zijn in het document.

Waarom is dit belangrijk?

Bij duplicate ID's pakt de browser doorgaans alleen de eerste. De verwijzing werkt dan niet correct voor andere elementen.

Hoe los je dit op?

Zorg dat alle ID's in het document uniek zijn. Gebruik een naming-conventie (component-naam + unieke suffix) om collisions te voorkomen.

Hoe controleer je dit?

DevTools console: let s = new Set(); document.querySelectorAll('[id]').forEach(e => { if(s.has(e.id)) console.log('dup:', e.id); else s.add(e.id); }); - hoort niets te loggen.

Middel om herhaalde blokken over te slaan

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Een pagina moet een mechanisme hebben om herhaalde content (header, navigatie) over te slaan. Meestal is dit een skip-link bovenaan, of een main landmark.

Waarom is dit belangrijk?

Toetsenbord-gebruikers moeten op elke pagina door dezelfde navigatie heen. Zonder skip-link kost dat tientallen tab-aanslagen per pagina.

Hoe los je dit op?

Plaats als eerste element op de pagina een zichtbare of focus-zichtbare skip-link naar #main. Alternatief: zorg dat er een main landmark is zodat schermlezers er direct naartoe kunnen springen.

Code voorbeeld
Correct
<a class="skip-link" href="#main">Skip to main content</a>
...
<main id="main">
Hoe controleer je dit?

Druk één keer Tab bij een frisse paginalading. De focus hoort op de skip-link te landen (zichtbaar).

Formuliervelden met labels

CriticalWCAG 2.0 A9x op 5 URLs
Wat controleert deze regel?

Elk formulierveld (input, textarea, select) moet een programmatisch gekoppeld label hebben.

Waarom is dit belangrijk?

Zonder label weet een schermlezer-gebruiker niet wat hij moet invullen. Placeholders zijn geen labels: ze verdwijnen bij het typen en worden niet altijd voorgelezen.

Hoe los je dit op?

Gebruik <label for="id"> of nest het input binnen <label>. Minimaal aria-label of aria-labelledby als een zichtbaar label niet kan.

Code voorbeeld
Fout
<input type="text" placeholder="Voornaam">
Correct
<label for="voornaam">Voornaam</label>
<input type="text" id="voornaam" name="voornaam">
Hoe controleer je dit?

Voor elk input: test met een schermlezer of de naam wordt voorgelezen bij focus.

Overtredingen op deze site 9
Impact
Critical
Prioriteit
High
Richtlijn
WCAG 2.0 A, WCAG 2.1 A, WCAG 2.2 A
Beschrijving
Form elements must have labels.
Standaard advies
Ensure every form element has a label that is either a child or referenced by for/id attributes.
Toon alle 9 vindplaatsen (5 unieke URLs)
URLLocatie op pagina (CSS selector)
https://www.website.nl/contactform#contact-form > div:nth-child(1) > input[name=naam]
https://www.website.nl/contactform#contact-form > div:nth-child(2) > input[name=email]
https://www.website.nl/contactform#contact-form > div:nth-child(3) > input[name=telefoon]
https://www.website.nl/contactform#contact-form > div:nth-child(5) > textarea[name=bericht]
https://www.website.nl/nieuwsbriefform.newsletter > input[type=email]
https://www.website.nl/nieuwsbriefform.newsletter > input[name=voornaam]
https://www.website.nl/footer form.signup > input[type=email]
https://www.website.nl/blogaside.widget-search > form > input[type=search]
https://www.website.nl/casesaside.widget-search > form > input[type=search]

Frames met title attribuut

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Elk <iframe> en <frame> hoort een beschrijvend title attribuut te hebben.

Waarom is dit belangrijk?

De schermlezer kondigt de titel aan als de gebruiker bij de iframe komt. Zonder title hoort de gebruiker alleen "frame" zonder wat erin zit.

Hoe los je dit op?

Geef elke iframe een title dat beschrijft wat er in staat. Niet "iframe" of "embedded content" maar bijvoorbeeld "Google Maps routebeschrijving naar kantoor".

Code voorbeeld
Correct
<iframe src="..." title="YouTube video: Introductie Joomla"></iframe>
Hoe controleer je dit?

Doorloop alle iframes op de site en controleer of elke een zinvolle title heeft.

Frames met uniek title attribuut

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Als een pagina meerdere iframes heeft, moeten de titles uniek zijn.

Waarom is dit belangrijk?

Twee iframes met dezelfde titel zijn niet van elkaar te onderscheiden voor schermlezer-gebruikers.

Hoe los je dit op?

Geef elke iframe een unieke, beschrijvende titel. Voeg context toe als de content van de iframes lijkt ("Video 1", "Video 2" is beter dan twee keer "Video").

Hoe controleer je dit?

DevTools: Array.from(document.querySelectorAll('iframe')).map(f=>f.title) - controleer op duplicaten.

Frames met focusbare content zonder tabindex=-1

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Een iframe met tabindex="-1" is niet bereikbaar via tab. Als de iframe focusbare content bevat, wordt die content onbereikbaar voor toetsenbord-gebruikers.

Waarom is dit belangrijk?

Een YouTube-embed met tabindex="-1" bevat knoppen die niet meer bereikbaar zijn. De gebruiker kan de video niet bedienen.

Hoe los je dit op?

Haal tabindex="-1" weg van iframes die interactieve content bevatten. Gebruik tabindex="-1" alleen op iframes met zuiver decoratieve content.

Hoe controleer je dit?

Tab door de pagina en controleer of je in elke iframe kunt komen.

Pagina bevat een <title>

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Elke pagina moet een niet-leeg <title> element in de <head> hebben.

Waarom is dit belangrijk?

De page title wordt getoond in browsertabs, bookmarks, zoekresultaten en is het eerste dat schermlezers voorlezen bij het openen van een pagina. Zonder title is oriëntatie onmogelijk.

Hoe los je dit op?

Zorg dat elke pagina (inclusief ajax-endpoints die als HTML worden gerenderd) een unieke, beschrijvende title heeft.

Code voorbeeld
Correct
<head>
  <title>Toegankelijkheidsrapport voor joomill.nl — Joomill</title>
</head>
Hoe controleer je dit?

Controleer voor elk pagina-type dat document.title een zinvolle waarde heeft.

Geldige lang waarde op <html>

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Het lang attribuut op <html> moet een geldige BCP 47 taalcode bevatten (bijvoorbeeld "nl", "en-US", "nl-BE").

Waarom is dit belangrijk?

Schermlezers gebruiken het lang attribuut om het juiste uitspraak-profiel te kiezen. Een ongeldige code (lang="dutch" in plaats van "nl") wordt genegeerd en de tekst klinkt dan als andere taal.

Hoe los je dit op?

Gebruik ISO 639-1 codes (nl, en, de, fr) eventueel met regio (nl-BE, en-GB). Niet "Dutch" of "nederlands".

Code voorbeeld
Fout
<html lang="dutch">
Correct
<html lang="nl">
Hoe controleer je dit?

Inspecteer het html element: lang attribuut moet voldoen aan BCP 47.

<html> vereist lang attribuut

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Het <html> element moet een lang attribuut hebben dat de primaire taal van de pagina aangeeft.

Waarom is dit belangrijk?

Zonder lang weet een schermlezer niet in welke taal hij moet voorlezen. Nederlandse tekst wordt dan in een Engels profiel uitgesproken, wat onverstaanbaar kan zijn.

Hoe los je dit op?

Voeg een lang attribuut toe aan het html element met de juiste taalcode.

Code voorbeeld
Correct
<html lang="nl">
Hoe controleer je dit?

DevTools: document.documentElement.lang moet een niet-lege, geldige waarde hebben.

Afbeeldingsknoppen met alt-tekst

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Een <input type="image"> wordt gerenderd als een klikbare afbeelding en heeft een alt attribuut nodig.

Waarom is dit belangrijk?

Zonder alt hoort de schermlezer alleen "submit button, image" zonder te weten wat de knop doet.

Hoe los je dit op?

Geef input type=image altijd een alt attribuut dat de actie beschrijft.

Code voorbeeld
Correct
<input type="image" src="search.png" alt="Zoeken">
Hoe controleer je dit?

Controleer in DevTools dat elk input type=image een alt attribuut heeft.

Afbeeldingen met alt-tekst

SeriousWCAG 2.0 A6x op 5 URLs
Wat controleert deze regel?

Elk <img> element moet een alt attribuut hebben. Voor decoratieve afbeeldingen mag dit leeg zijn (alt=""), maar het attribuut moet aanwezig zijn.

Waarom is dit belangrijk?

Schermlezer-gebruikers krijgen de alt-tekst als beschrijving. Zonder alt wordt de bestandsnaam (image_12345.jpg) voorgelezen, wat betekenisloos is. Bij geen alt en ook geen bestandsnaam hoort de gebruiker alleen "image".

Hoe los je dit op?

Voeg een alt attribuut toe aan elke img. Voor decoratieve afbeeldingen (sierrand, achtergrondfoto zonder inhoudelijke waarde): alt="". Voor informatieve afbeeldingen: beschrijf wat er te zien is in de context van de pagina.

Code voorbeeld
Fout
<img src="team.jpg">
Correct
<img src="team.jpg" alt="Team Joomill bij de kantooropening">
Hoe controleer je dit?

DevTools: Array.from(document.images).filter(i => i.alt === undefined).length - hoort 0 te zijn (let op: lege alt="" is geldig).

Overtredingen op deze site 6
Impact
Serious
Prioriteit
High
Richtlijn
WCAG 2.0 A, WCAG 2.1 A, WCAG 2.2 A, Section 508
Beschrijving
Images must have alternate text.
Standaard advies
Add alt attributes with meaningful descriptions to all images, or alt="" for decorative images.
Toon alle 6 vindplaatsen (5 unieke URLs)
URLLocatie op pagina (CSS selector)
https://www.website.nl/main > section.hero > img.hero-banner
https://www.website.nl/over-onsmain > section.team > img:nth-child(2)
https://www.website.nl/over-onsmain > section.team > img:nth-child(4)
https://www.website.nl/cases/gemeente-amersfoortarticle > figure > img
https://www.website.nl/blog/toegankelijkheid-in-2026article > figure:nth-of-type(2) > img
https://www.website.nl/blog/kleurcontrast-in-de-praktijkarticle > img.kleurwiel

<object> elementen met alt-tekst

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Het <object> element (embed van externe content zoals PDFs of Flash) moet een tekstuele fallback bieden binnen het object.

Waarom is dit belangrijk?

Als de embed niet geladen kan worden, of de gebruiker een schermlezer gebruikt, moet er alternatieve tekst zijn.

Hoe los je dit op?

Plaats beschrijvende tekst binnen het <object> element of gebruik een title attribuut.

Code voorbeeld
Correct
<object data="brochure.pdf" type="application/pdf">
  <p>Download de <a href="brochure.pdf">Brochure (PDF, 1MB)</a></p>
</object>
Hoe controleer je dit?

Inspecteer elke <object> in DevTools op fallback content of title.

Actieve <area> elementen met alt-tekst

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

In een image map moet elke klikbare <area> een alt attribuut hebben dat de bestemming beschrijft.

Waarom is dit belangrijk?

Een area zonder alt is een link zonder tekst voor schermlezer-gebruikers.

Hoe los je dit op?

Geef elke area een alt die de doelpagina of actie beschrijft.

Code voorbeeld
Correct
<map name="wereld">
  <area shape="rect" coords="0,0,100,100" href="/nl" alt="Nederland">
</map>
Hoe controleer je dit?

Doorloop image maps en controleer alt attributen op elke area met href.

Elementen met role=img hebben alt-tekst nodig

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Een element met role="img" (meestal gebruikt voor icoonbundels of CSS-afbeeldingen) moet een toegankelijke naam hebben.

Waarom is dit belangrijk?

Zonder naam wordt het element als afbeelding aangekondigd zonder beschrijving van wat er te zien is.

Hoe los je dit op?

Gebruik aria-label of aria-labelledby op het element met role="img".

Code voorbeeld
Correct
<span role="img" aria-label="Rode waarschuwing">⚠️</span>
Hoe controleer je dit?

Controleer alle elementen met role=img op een toegankelijke naam via DevTools Accessibility panel.

SVG afbeeldingen met toegankelijke tekst

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Inline SVG moet een <title> element als eerste kind hebben, of gebruik maken van aria-label/aria-labelledby.

Waarom is dit belangrijk?

SVG zonder title wordt door schermlezers niet aangekondigd. Voor informatieve iconen (statusindicatoren, grafieken) is dat een probleem.

Hoe los je dit op?

Voeg <title> toe als eerste kind van de SVG. Als het icoon decoratief is, gebruik role="img" aria-hidden="true" of geef role="presentation".

Code voorbeeld
Correct
<svg role="img" aria-labelledby="t1">
  <title id="t1">Groen vinkje: voltooid</title>
  <path .../>
</svg>
Hoe controleer je dit?

Controleer met DevTools Accessibility panel of SVG's de juiste naam hebben.

<video> elementen met <track> voor ondertiteling

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Video's met geluid hebben ondertiteling nodig via een <track kind="captions"> element.

Waarom is dit belangrijk?

Doven en slechthorenden kunnen de gesproken inhoud anders niet volgen. Ook mensen in luidruchtige omgevingen of met geluid uit profiteren.

Hoe los je dit op?

Voeg een track element toe naar een WebVTT ondertitelingsbestand. Voor YouTube embeds: schakel ondertiteling in en zorg dat er goede captions (niet alleen auto-generated) beschikbaar zijn.

Code voorbeeld
Correct
<video controls>
  <source src="video.mp4" type="video/mp4">
  <track kind="captions" src="nl.vtt" srclang="nl" label="Nederlands">
</video>
Hoe controleer je dit?

Speel elke video af en controleer of ondertiteling zichtbaar is.

<video> of <audio> zonder auto-play

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Media mag niet automatisch afspelen met geluid als de gebruiker daar geen controle over heeft. De gebruiker moet het kunnen stoppen binnen korte tijd.

Waarom is dit belangrijk?

Onverwacht audio interfereert met schermlezers. De gebruiker kan mogelijk niet eens de controls vinden om te stoppen.

Hoe los je dit op?

Verwijder het autoplay attribuut, of zorg dat media muted start en duidelijke pauze-controls heeft.

Code voorbeeld
Fout
<video autoplay src="intro.mp4"></video>
Correct
<video controls src="intro.mp4"></video>
Hoe controleer je dit?

Laad elke pagina met media en controleer of er nergens onverwacht geluid speelt.

Knoppen met duidelijke tekst

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Elke <button> moet tekstinhoud of een aria-label hebben die aangeeft wat de knop doet.

Waarom is dit belangrijk?

Een lege knop of een knop met alleen een icoon zonder aria-label is niet bruikbaar voor schermlezer-gebruikers. De gebruiker hoort "button" zonder te weten welke actie volgt.

Hoe los je dit op?

Zet tekst in de knop, of voeg aria-label toe voor icoon-knoppen. Maak icoon-elementen binnen de knop aria-hidden.

Code voorbeeld
Fout
<button><i class="icon-close"></i></button>
Correct
<button aria-label="Sluiten"><i class="icon-close" aria-hidden="true"></i></button>
Hoe controleer je dit?

Tab naar elke knop en luister wat een schermlezer zegt. "button" zonder extra info is fout.

Input knoppen met duidelijke tekst

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

<input type="submit">, <input type="button"> en <input type="reset"> moeten een value attribuut hebben dat de actie beschrijft.

Waarom is dit belangrijk?

Zonder value gebruikt de browser een default tekst ("Submit") die niet altijd de actie beschrijft. Met een lege value hoort de schermlezer niets.

Hoe los je dit op?

Geef elke input van deze types een beschrijvende value.

Code voorbeeld
Fout
<input type="submit">
Correct
<input type="submit" value="Versturen">
Hoe controleer je dit?

Inspecteer elk input element van button-types en controleer op een zinvolle value.

<select> element met toegankelijke naam

CriticalWCAG 2.0 A2x op 2 URLs
Wat controleert deze regel?

Een <select> dropdown moet gekoppeld zijn aan een label of een aria-label hebben.

Waarom is dit belangrijk?

Zonder naam weet een schermlezer-gebruiker niet wat hij uit de dropdown kiest. Typische select-opties als "Kies een optie" bieden onvoldoende context.

Hoe los je dit op?

Koppel een <label for="id"> aan het select element, of gebruik aria-label.

Code voorbeeld
Correct
<label for="land">Land</label>
<select id="land">
  <option>Nederland</option>
  <option>België</option>
</select>
Hoe controleer je dit?

Tab naar elke select en controleer of de naam wordt voorgelezen.

Overtredingen op deze site 2
Impact
Critical
Prioriteit
High
Richtlijn
WCAG 2.0 A, WCAG 2.1 A, WCAG 2.2 A
Beschrijving
Select elements must have an accessible name.
Standaard advies
Associate a label with the select element using a label element or aria-label.
Toon alle 2 vindplaatsen (2 unieke URLs)
URLLocatie op pagina (CSS selector)
https://www.website.nl/casesmain > div.filter-bar > select[name=branche]
https://www.website.nl/blogaside.widget-filter > select[name=categorie]

<summary> elementen met duidelijke tekst

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Een <summary> binnen een <details> element moet tekstinhoud hebben zodat de gebruiker weet wat er kan worden uitgeklapt.

Waarom is dit belangrijk?

Een lege summary geeft een anoniem uitklapbaar element. De gebruiker weet niet wat zich erachter bevindt.

Hoe los je dit op?

Zorg voor een duidelijke tekst in elke summary.

Code voorbeeld
Correct
<details>
  <summary>Veelgestelde vragen</summary>
  <p>...</p>
</details>
Hoe controleer je dit?

Controleer alle details/summary combinaties op niet-lege summary tekst.

Geen verouderd <marquee> element

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Het <marquee> element (scrollende tekst) is verouderd en niet toegankelijk.

Waarom is dit belangrijk?

Scrollende tekst kan epilepsie triggeren, is lastig te lezen voor mensen met leesbeperkingen en kan niet worden gepauzeerd zonder aanvullende controls.

Hoe los je dit op?

Verwijder marquee elementen. Als scrollende content echt nodig is, bouw het dan met CSS animation met respect voor prefers-reduced-motion en voorzie een pauzeknop.

Hoe controleer je dit?

Zoek in de DOM naar marquee elementen: er horen er geen te zijn.

Geen geneste interactieve controls

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Interactieve elementen (links, knoppen, inputs) mogen niet genest worden binnen andere interactieve elementen.

Waarom is dit belangrijk?

Een knop binnen een link levert onvoorspelbaar klikgedrag en is voor schermlezer-gebruikers onnavigeerbaar: ze horen de geneste rollen door elkaar.

Hoe los je dit op?

Ontkoppel de interactieve elementen. Gebruik CSS om het visuele effect te bereiken zonder neste interactie.

Code voorbeeld
Fout
<a href="/item"><button>Kopen</button></a>
Correct
<div class="card">
  <a href="/item">Item naam</a>
  <button>Kopen</button>
</div>
Hoe controleer je dit?

DevTools: document.querySelectorAll('a a, a button, button a, button button') - hoort geen resultaten op te leveren.

<li> elementen in lijstelementen

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Een <li> element hoort binnen een <ul>, <ol> of <menu> te staan.

Waarom is dit belangrijk?

Losse li elementen zijn semantisch betekenisloos en worden door schermlezers niet als lijst aangekondigd.

Hoe los je dit op?

Wikkel li elementen altijd in ul of ol. Als een structuur geen lijst is, gebruik dan een andere tag.

Hoe controleer je dit?

DevTools: Array.from(document.querySelectorAll('li')).filter(l => !['UL','OL','MENU'].includes(l.parentElement?.tagName)).length - hoort 0 te zijn.

Lijsten bevatten alleen <li> content

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Een <ul> of <ol> mag als directe kinderen alleen <li> elementen bevatten (plus script en template).

Waarom is dit belangrijk?

Losse divs of spans binnen ul/ol doorbreken de lijst-semantiek. Schermlezers kondigen de lijstlengte verkeerd aan.

Hoe los je dit op?

Plaats alle content binnen li elementen, ook als het om wrapper-divs gaat.

Code voorbeeld
Fout
<ul>
  <div class="wrapper">
    <li>Item</li>
  </div>
</ul>
Correct
<ul>
  <li><div class="wrapper">Item</div></li>
</ul>
Hoe controleer je dit?

Inspecteer elke lijst: alle directe kinderen moeten li zijn.

<dt> en <dd> binnen <dl>

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Definition terms (<dt>) en definition descriptions (<dd>) moeten binnen een definition list (<dl>) staan.

Waarom is dit belangrijk?

Losse dt/dd elementen zijn semantisch verbroken en worden niet als definitielijst aangekondigd.

Hoe los je dit op?

Wikkel dt/dd altijd in dl.

Code voorbeeld
Correct
<dl>
  <dt>Joomla</dt>
  <dd>Een open-source CMS</dd>
</dl>
Hoe controleer je dit?

Zoek in DOM naar losse dt/dd elementen zonder dl parent.

<dl> bevat geordende dt- en dd-groepen

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Een definition list moet een logische volgorde van dt gevolgd door één of meer dd hebben. Of als alternatief, groepering in <div> wrappers.

Waarom is dit belangrijk?

Verkeerde structuur breekt de semantische relatie tussen term en definitie.

Hoe los je dit op?

Zorg voor een correcte structuur: dt, dan dd (eventueel meerdere), dan volgende dt. Geen losse dd zonder voorafgaande dt.

Code voorbeeld
Correct
<dl>
  <dt>CMS</dt>
  <dd>Content Management System</dd>
  <dt>SEO</dt>
  <dd>Search Engine Optimization</dd>
</dl>
Hoe controleer je dit?

Inspecteer definition lists op correcte term/description paren.

<th> met gekoppelde datacellen

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Een th element hoort bijbehorende td cellen te hebben in de tabel. Anders beschrijft de header geen data.

Waarom is dit belangrijk?

Een th zonder bijbehorende data is structureel zinloos en verwarrend voor schermlezer-gebruikers.

Hoe los je dit op?

Zorg dat elke th in een tabel datacellen (td) in dezelfde rij of kolom heeft.

Hoe controleer je dit?

Inspecteer datatabellen: elke header moet data onder zich hebben.

headers attribuut verwijst naar zelfde tabel

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Als een td het headers attribuut gebruikt om naar headers te verwijzen, moeten die headers in dezelfde tabel staan.

Waarom is dit belangrijk?

Een verwijzing naar een header in een andere tabel of naar een niet-bestaand ID is een gebroken relatie.

Hoe los je dit op?

Controleer dat alle waarden in headers attributen overeenkomen met ID's van th elementen binnen dezelfde tabel.

Hoe controleer je dit?

Inspecteer td headers attributen en match ze met th ID's binnen hetzelfde tabel-element.

Formulierveld met één label

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Een input hoort gekoppeld te zijn aan één label element. Twee labels voor hetzelfde veld veroorzaken onvoorspelbare aankondiging.

Waarom is dit belangrijk?

Schermlezers kondigen meestal alleen het eerste label aan, waardoor informatie in het tweede label verloren gaat.

Hoe los je dit op?

Combineer de tekst in één label. Als je extra tekst wilt koppelen (hint-tekst), gebruik aria-describedby in plaats van een tweede label.

Code voorbeeld
Correct
<label for="wachtwoord">Wachtwoord <span class="hint">(minstens 8 tekens)</span></label>
<input type="password" id="wachtwoord">
Hoe controleer je dit?

DevTools: Array.from(document.querySelectorAll('label[for]')).reduce((a,l)=>(a[l.htmlFor]=(a[l.htmlFor]||0)+1,a),{}) - geen ID mag waarde >1 hebben.

HTML lang en XML lang moeten overeenkomen

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Als zowel lang als xml:lang op het html element staan, moeten ze dezelfde taalcode bevatten.

Waarom is dit belangrijk?

Tegenstrijdige taal-attributen kunnen afhankelijk van de user agent verschillend worden geïnterpreteerd.

Hoe los je dit op?

Stel dezelfde waarde in voor beide, of verwijder xml:lang (alleen nodig voor XHTML).

Hoe controleer je dit?

Inspecteer html element: als beide attributen aanwezig zijn, moeten ze identiek zijn.

Geen verouderde ARIA rollen

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Enkele ARIA rollen zijn verouderd (bijvoorbeeld role="directory") en moeten niet meer gebruikt worden.

Waarom is dit belangrijk?

Verouderde rollen worden door moderne assistive technology niet meer goed ondersteund.

Hoe los je dit op?

Vervang verouderde rollen door hun moderne equivalenten: role="directory" wordt role="list".

Hoe controleer je dit?

Zoek in DOM naar verouderde role-waarden volgens de actuele ARIA specificatie.

Geen server-side image maps

GeslaagdWCAG 2.0 A
Wat controleert deze regel?

Een <img ismap> (server-side image map) stuurt alleen kliklocaties naar de server. Deze techniek is niet bereikbaar voor schermlezers of toetsenbord-gebruikers.

Waarom is dit belangrijk?

Zonder beschrijvingen kunnen niet-visuele gebruikers de kliklocaties niet identificeren. De techniek is volledig afhankelijk van visuele interactie.

Hoe los je dit op?

Vervang server-side image maps door client-side image maps (<map> met <area alt>) of door echte HTML links op de afbeelding.

Hoe controleer je dit?

Zoek in DOM naar img elementen met het ismap attribuut: er mogen er geen zijn.

WCAG 2.0 AA

2 van 3 regels geslaagd · 39 overtredingen

Viewport zoom en scaling niet uitschakelen

GeslaagdWCAG 2.0 AA
Wat controleert deze regel?

De meta viewport mag niet user-scalable=no bevatten, want dat blokkeert de gebruiker om in te zoomen.

Waarom is dit belangrijk?

Mensen met een visuele beperking hebben vaak zoom nodig. Zonder zoom is content onleesbaar voor hen. Dit is een harde WCAG 2.0 AA vereiste onder Succescriterium 1.4.4 (Resize text).

Hoe los je dit op?

Verwijder user-scalable=no uit de viewport meta tag. Verwijder ook maximum-scale als die op 1 staat.

Code voorbeeld
Fout
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
Correct
<meta name="viewport" content="width=device-width, initial-scale=1">
Hoe controleer je dit?

Open de site op mobiel en probeer te zoomen met pinch-gesture. Als het werkt, is het goed.

lang attribuut met geldige waarde

GeslaagdWCAG 2.0 AA
Wat controleert deze regel?

Elk lang attribuut in het document (niet alleen op html) moet een geldige BCP 47 taalcode bevatten.

Waarom is dit belangrijk?

Schermlezers schakelen tussen taalprofielen op basis van het lang attribuut. Ongeldige codes worden genegeerd en Nederlandse tekst wordt in Engels uitgesproken, wat onverstaanbaar klinkt.

Hoe los je dit op?

Gebruik correcte ISO taalcodes: nl, en, de, fr, nl-BE, en-US, enzovoort. Niet lang="nederlands" of lang="dutch".

Code voorbeeld
Fout
<p lang="nederlands">Welkom</p>
Correct
<p lang="nl">Welkom</p>
Hoe controleer je dit?

DevTools: Array.from(document.querySelectorAll('[lang]')).map(e => e.lang) - alle waarden moeten geldige taalcodes zijn.

Voldoende kleurcontrast (AA)

SeriousWCAG 2.0 AA39x op 17 URLs
Wat controleert deze regel?

Tekst moet voldoende contrast hebben ten opzichte van de achtergrond. WCAG 2.0 AA vereist minstens 4.5:1 voor normale tekst en 3:1 voor grote tekst (18pt+ of 14pt+ bold).

Waarom is dit belangrijk?

Mensen met een visuele beperking, kleurenblindheid of ouderdomsgerelateerd slecht zicht hebben contrast nodig om tekst te kunnen lezen. Dit is een harde eis voor WCAG 2.0 AA en daarmee voor de European Accessibility Act.

Hoe los je dit op?

Check alle tekst-op-achtergrond combinaties met een contrast-tool. Pas kleuren aan tot ze voldoen aan 4.5:1 (normaal) of 3:1 (groot/dikgedrukt). Vooral probleemgevallen: grijze tekst op witte achtergrond, gekleurde links op lichte achtergrond, tekst op afbeeldingen.

Code voorbeeld
Fout
body { color: #999; } /* grijs op wit = 2.85:1 - onvoldoende */
Correct
body { color: #595959; } /* = 7.0:1 - ruim voldoende */
Hoe controleer je dit?

Gebruik de WebAIM Contrast Checker of de ingebouwde contrast tool in Chrome DevTools (Accessibility pane). Test tegen de daadwerkelijke achtergrond, niet de body-kleur.

Handige tools

WebAIM Contrast Checker, Chrome DevTools Accessibility, Stark, Contrast (macOS)

Overtredingen op deze site 39
Impact
Serious
Prioriteit
High
Richtlijn
WCAG 2.0 AA, WCAG 2.1 AA, WCAG 2.2 AA
Beschrijving
Elements must meet minimum color contrast ratio thresholds.
Standaard advies
Ensure all text elements have sufficient color contrast between the text in the foreground and background color behind it.
Toon alle 39 vindplaatsen (17 unieke URLs)
URLLocatie op pagina (CSS selector)
https://www.website.nl/p.intro
https://www.website.nl/.muted-text
https://www.website.nl/footer p.copyright
https://www.website.nl/a.read-more
https://www.website.nl/over-onsp.intro
https://www.website.nl/over-ons.muted-text
https://www.website.nl/dienstenp.intro
https://www.website.nl/diensten.muted-text
https://www.website.nl/dienstenfooter p.copyright
https://www.website.nl/diensten/adviesp.intro
https://www.website.nl/diensten/advies.muted-text
https://www.website.nl/diensten/implementatiep.intro
https://www.website.nl/diensten/implementatie.muted-text
https://www.website.nl/diensten/onderhoudp.intro
https://www.website.nl/diensten/onderhoud.muted-text
https://www.website.nl/casesp.intro
https://www.website.nl/cases.muted-text
https://www.website.nl/casesfooter p.copyright
https://www.website.nl/cases/gemeente-amersfoortp.intro
https://www.website.nl/cases/gemeente-amersfoort.muted-text
https://www.website.nl/cases/zorginstelling-noordp.intro
https://www.website.nl/cases/zorginstelling-noord.muted-text
https://www.website.nl/cases/retailketen-westp.intro
https://www.website.nl/cases/retailketen-west.muted-text
https://www.website.nl/blogp.intro
https://www.website.nl/blog.muted-text
https://www.website.nl/blogfooter p.copyright
https://www.website.nl/blog/toegankelijkheid-in-2026p.intro
https://www.website.nl/blog/toegankelijkheid-in-2026.muted-text
https://www.website.nl/blog/waarom-wcag-belangrijk-isp.intro
https://www.website.nl/blog/waarom-wcag-belangrijk-is.muted-text
https://www.website.nl/blog/5-tips-voor-betere-formulierenp.intro
https://www.website.nl/blog/5-tips-voor-betere-formulieren.muted-text
https://www.website.nl/blog/kleurcontrast-in-de-praktijkp.intro
https://www.website.nl/blog/kleurcontrast-in-de-praktijk.muted-text
https://www.website.nl/blog/gebruikerstest-met-schermlezerp.intro
https://www.website.nl/blog/gebruikerstest-met-schermlezer.muted-text
https://www.website.nl/contactp.intro
https://www.website.nl/contact.muted-text

WCAG 2.0 AAA

2 van 3 regels geslaagd · 45 overtredingen

Verhoogd kleurcontrast (AAA)

SeriousWCAG 2.0 AAA45x op 20 URLs
Wat controleert deze regel?

Het verhoogde contrast niveau voor AAA is 7:1 voor normale tekst en 4.5:1 voor grote tekst. Dit is strenger dan de AA eis.

Waarom is dit belangrijk?

Voor mensen met een ernstige visuele beperking geeft AAA contrast echt leeskomfort. Voor commerciële sites is dit geen harde wettelijke eis, maar meenemen is verstandig omdat AAA-compliance vaak de UX voor iedereen verbetert.

Hoe los je dit op?

Verhoog contrast naar 7:1 voor hoofdtekst. In de praktijk: zwart (#000) of bijna-zwart (#111) op wit (#fff), of wit op donkerblauw (#003366). Grijze tekst werkt vaak niet voor AAA.

Code voorbeeld
Correct
body { color: #1a1a1a; } /* = 17.4:1 - AAA */
Hoe controleer je dit?

Zelfde tools als AA-contrast, maar met AAA-drempels. Focus op hoofdtekst en headings eerst.

Handige tools

WebAIM Contrast Checker (set to AAA)

Overtredingen op deze site 45
Impact
Serious
Prioriteit
Medium
Richtlijn
WCAG 2.0 AAA
Beschrijving
Elements must meet enhanced color contrast ratio thresholds.
Standaard advies
Ensure all text elements have enhanced color contrast (7:1 for normal text, 4.5:1 for large text).
Toon alle 45 vindplaatsen (20 unieke URLs)
URLLocatie op pagina (CSS selector)
https://www.website.nl/body
https://www.website.nl/p
https://www.website.nl/.card p
https://www.website.nl/over-onsbody
https://www.website.nl/over-onsp
https://www.website.nl/dienstenbody
https://www.website.nl/dienstenp
https://www.website.nl/diensten.card p
https://www.website.nl/diensten/adviesbody
https://www.website.nl/diensten/adviesp
https://www.website.nl/diensten/implementatiebody
https://www.website.nl/diensten/implementatiep
https://www.website.nl/diensten/onderhoudbody
https://www.website.nl/diensten/onderhoudp
https://www.website.nl/casesbody
https://www.website.nl/casesp
https://www.website.nl/cases.card p
https://www.website.nl/cases/gemeente-amersfoortbody
https://www.website.nl/cases/gemeente-amersfoortp
https://www.website.nl/cases/zorginstelling-noordbody
https://www.website.nl/cases/zorginstelling-noordp
https://www.website.nl/cases/retailketen-westbody
https://www.website.nl/cases/retailketen-westp
https://www.website.nl/blogbody
https://www.website.nl/blogp
https://www.website.nl/blog.card p
https://www.website.nl/blog/toegankelijkheid-in-2026body
https://www.website.nl/blog/toegankelijkheid-in-2026p
https://www.website.nl/blog/waarom-wcag-belangrijk-isbody
https://www.website.nl/blog/waarom-wcag-belangrijk-isp
https://www.website.nl/blog/5-tips-voor-betere-formulierenbody
https://www.website.nl/blog/5-tips-voor-betere-formulierenp
https://www.website.nl/blog/kleurcontrast-in-de-praktijkbody
https://www.website.nl/blog/kleurcontrast-in-de-praktijkp
https://www.website.nl/blog/kleurcontrast-in-de-praktijk.card p
https://www.website.nl/blog/gebruikerstest-met-schermlezerbody
https://www.website.nl/blog/gebruikerstest-met-schermlezerp
https://www.website.nl/contactbody
https://www.website.nl/contactp
https://www.website.nl/nieuwsbriefbody
https://www.website.nl/nieuwsbriefp
https://www.website.nl/privacybody
https://www.website.nl/privacyp
https://www.website.nl/voorwaardenbody
https://www.website.nl/voorwaardenp

Geen vertraagde meta refresh

GeslaagdWCAG 2.0 AAA
Wat controleert deze regel?

Een meta refresh met een vertraging (bijvoorbeeld <meta http-equiv="refresh" content="30;url=...">) laadt de pagina na tijd automatisch opnieuw.

Waarom is dit belangrijk?

Een automatische refresh onderbreekt gebruikers die traag lezen of door content navigeren. Schermlezer-gebruikers kunnen hierdoor hun positie verliezen.

Hoe los je dit op?

Vervang meta refresh door een gebruikersgestuurde knop ("Vernieuwen"), of biedt de optie om de refresh uit te stellen of uit te schakelen. Server-side HTTP redirects (status 301/302) zijn geen issue.

Code voorbeeld
Fout
<meta http-equiv="refresh" content="30;url=/new-page">
Hoe controleer je dit?

Zoek in HTML source naar meta refresh met numerieke vertraging.

WCAG 2.1 AA

2 van 2 regels geslaagd · 0 overtredingen

Correct gebruik van autocomplete attribuut

GeslaagdWCAG 2.1 AA
Wat controleert deze regel?

Het autocomplete attribuut op formuliervelden moet geldige waarden uit de HTML specificatie gebruiken (bijvoorbeeld "email", "given-name", "postal-code").

Waarom is dit belangrijk?

Autocomplete helpt alle gebruikers, maar is essentieel voor mensen met cognitieve of motorische beperkingen die geen lange formulieren handmatig willen invullen. Ongeldige waarden schakelen de browser-autocomplete uit. Dit is onder WCAG 2.1 AA succescriterium 1.3.5 (Identify Input Purpose).

Hoe los je dit op?

Gebruik de standaard autocomplete waarden. Voor gebruikers: "given-name", "family-name", "email", "tel", "street-address", "postal-code", "country". Voor betalingen: "cc-number", "cc-exp". Zie de HTML Living Standard voor de volledige lijst.

Code voorbeeld
Fout
<input name="email" autocomplete="yes">
Correct
<input name="email" autocomplete="email" type="email">
Hoe controleer je dit?

Browser autocomplete test: begin in te vullen en controleer of de browser suggesties biedt uit eerder opgeslagen gegevens.

Inline tekstafstand moet aanpasbaar zijn

GeslaagdWCAG 2.1 AA
Wat controleert deze regel?

Als gebruikers de tekstafstand aanpassen (line-height, letter-spacing, word-spacing, paragraph spacing) mag er geen content verloren gaan of overlappen.

Waarom is dit belangrijk?

Mensen met dyslexie of visuele beperkingen passen vaak tekstafstand aan via browser-extensies om beter te kunnen lezen. Als de site daarvan breekt (tekst valt uit containers, kop wordt niet zichtbaar), is hij onbruikbaar.

Hoe los je dit op?

Vermijd vaste hoogtes en overflow:hidden op tekst-containers. Gebruik min-height in plaats van height. Laat containers meeschalen met de content.

Code voorbeeld
Fout
.card { height: 120px; overflow: hidden; }
Correct
.card { min-height: 120px; }
Hoe controleer je dit?

Installeer een bookmarklet die line-height, letter-spacing etc. injecteert volgens WCAG 2.1 drempels (line-height 1.5x, letter-spacing 0.12em, etc.) en controleer of de pagina nog werkt.

WCAG 2.2 AA

0 van 1 regels geslaagd · 4 overtredingen

Voldoende grootte en ruimte voor touch targets

ModerateWCAG 2.2 AA4x op 2 URLs
Wat controleert deze regel?

Klikbare elementen moeten minimaal 24x24 CSS pixels groot zijn, of voldoende ruimte om zich heen hebben zodat gebruikers met motorische beperkingen ze kunnen raken.

Waarom is dit belangrijk?

Mensen met tremor, Parkinson of andere motorische beperkingen kunnen kleine knoppen niet nauwkeurig raken. Ook op mobiele devices met kleine schermen helpt grotere tap-targets. Dit is onder WCAG 2.2 AA succescriterium 2.5.8.

Hoe los je dit op?

Maak klikbare elementen minimaal 24x24px. Als dat om visuele redenen niet kan, zorg dan voor padding of margin zodat de klikbare zone effectief 24x24 is (bijvoorbeeld een klein icoon met padding eromheen in dezelfde link). Pictogrammen in knoppenreeksen: minstens 24px tussen twee centers.

Code voorbeeld
Fout
.social-icon { width: 16px; height: 16px; padding: 0; margin: 2px; }
Correct
.social-icon { width: 16px; height: 16px; padding: 8px; } /* totaal 32px klikbare zone */
Hoe controleer je dit?

Meet in DevTools de klikbare zone (inclusief padding) van kleine knoppen, social iconen, close-buttons en dropdown-opties. Onder 24px: fix.

Overtredingen op deze site 4
Impact
Moderate
Prioriteit
Medium
Richtlijn
WCAG 2.2 AA
Beschrijving
Touch targets must have sufficient size and spacing.
Standaard advies
Ensure touch targets are at least 24 by 24 CSS pixels, or have sufficient spacing around them.
Toon alle 4 vindplaatsen (2 unieke URLs)
URLLocatie op pagina (CSS selector)
https://www.website.nl/footer > ul.social > li:nth-child(1) > a
https://www.website.nl/footer > ul.social > li:nth-child(2) > a
https://www.website.nl/footer > ul.social > li:nth-child(3) > a
https://www.website.nl/blog/toegankelijkheid-in-2026div.article-actions > button.share-twitter

4. Methodiek en achtergrond

Dit rapport is gegenereerd door middel van een geautomatiseerde toegankelijkheidsaudit waarbij elke gecrawlde pagina wordt getest tegen 92 regels uit WCAG 2.0, WCAG 2.1, WCAG 2.2 en een set breed geaccepteerde best practices. De onderliggende testengine is open-source en wordt door partijen als Google Lighthouse en Chrome DevTools gebruikt voor hun eigen toegankelijkheidsaudits, wat de resultaten vergelijkbaar maakt met andere gangbare tooling.

Regelgroepen en telling

De 92 regels zijn als volgt verdeeld:

GroepRegelsToelichting
Best Practice28Geen directe WCAG criteria maar breed geaccepteerde richtlijnen die de gebruikerservaring verbeteren.
WCAG 2.0 A55Basisniveau van WCAG 2.0, verplicht voor iedere toegankelijke website.
WCAG 2.0 AA3Aanvullende regels voor AA niveau. A + AA is het wettelijk minimum voor veel publieke sites en voor de EAA.
WCAG 2.0 AAA3Hoogste niveau van WCAG 2.0, niet verplicht maar aanbevolen waar mogelijk.
WCAG 2.1 AA2Uitbreiding van WCAG 2.0 met extra criteria voor mobiel en cognitieve toegankelijkheid.
WCAG 2.2 AA1Nieuwste uitbreiding (2023) met onder andere minimale afmetingen voor touch targets.
Totaal: 92 regels

Beperkingen van geautomatiseerde tests

Automatische tools vangen tussen de 30% en 40% van alle mogelijke toegankelijkheidsproblemen af. Zaken als logische volgorde van content, zinvolheid van alt-teksten, toetsenbordbediening van complexe widgets en ondertiteling van video kunnen alleen handmatig worden beoordeeld. Voor volledige WCAG conformiteit in het kader van de European Accessibility Act (van kracht sinds 28 juni 2025) is aanvullend handmatig onderzoek en idealiter gebruikerstest met mensen met een beperking nodig.

Impactniveaus

CriticalBlokkeert het gebruik van een functie volledig voor mensen met bepaalde beperkingen.
SeriousVeroorzaakt ernstige belemmeringen, het gebruik blijft met moeite mogelijk.
ModerateMerkbare hinder, maar het gebruik blijft redelijk mogelijk.

Aanbevolen workflow voor herstel

  1. Begin bij de prioriteitenlijst in sectie 2 en werk de top naar beneden af.
  2. Pak categorieën in plaats van individuele URL's aan. Kleurcontrast los je op in de CSS variabelen, niet op 47 losse pagina's.
  3. Na elke categorie: een hertest op een subset van URL's om voortgang te meten.
  4. Herhaal totdat alle Critical en Serious issues zijn opgelost.
  5. Doe daarna een handmatige controle op de top 10 meest bezochte pagina's met een schermlezer (NVDA gratis op Windows, VoiceOver ingebouwd op macOS).
  6. Overweeg een gebruikerstest met iemand die dagelijks assistive technology gebruikt.

Handige tools

axe DevToolsBrowser-extensie voor Chrome en Firefox die direct toegankelijkheidsfouten op de huidige pagina toont.
WebAIM WAVEBrowser-extensie met visuele feedback over toegankelijkheidsproblemen direct op de pagina.
WebAIM Contrast CheckerOnline tool voor het testen van kleurcombinaties tegen WCAG AA en AAA drempels.
LighthouseIngebouwd in Chrome DevTools, geeft een score van 0 tot 100 plus concrete adviezen.
NVDAGratis schermlezer voor Windows, de meest gebruikte in Nederland.
VoiceOverIngebouwde schermlezer op macOS en iOS.
Landmarks browser-extensieVisualiseert alle landmarks op een pagina en laat zien waar content buiten landmarks valt.
HeadingsMapBrowser-extensie die de heading-hiërarchie van een pagina visualiseert.