ARIA-rollen uitgelegd: wanneer en hoe ARIA in HTML te gebruiken

15 min read

ARIA (Accessible Rich Internet Applications) geeft ontwikkelaars een krachtig hulpmiddel om dynamische, complexe webinterfaces toegankelijk te maken voor schermlezers — maar verkeerd gebruik is wijdverbreid en kostbaar. Deze gids behandelt elke belangrijke ARIA-rolcategorie, legt de gouden regels voor ARIA-gebruik uit en laat je concrete codevoorbeelden zien zodat je het correct kunt toepassen.

Hier is een ontnuchterend getal: volgens WebAIM's analyse van de top één miljoen homepage’s van websites bevatten pagina’s die ARIA-attributen gebruiken gemiddeld aanzienlijk meer detecteerbare toegankelijkheidsfouten dan pagina’s zonder ARIA. Dat is geen argument tégen het gebruik van ARIA — het is een argument vóór het correcte gebruik ervan. ARIA is een van de krachtigste tools in de moderne toegankelijkheidsgereedschapskist, maar ook een van de meest verkeerd begrepen. Doe het goed en je opent je site op een betekenisvolle manier voor miljoenen gebruikers met een beperking. Doe het fout en je maakt hun ervaring actief slechter.

Wat Is ARIA en Waarom Bestaat Het?

ARIA staat voor Accessible Rich Internet Applications. Het is een set HTML-attributen, gedefinieerd door het Web Accessibility Initiative van het W3C, waarmee ontwikkelaars semantische informatie kunnen communiceren naar ondersteunende technologieën zoals schermlezers, brailleleesregels en spraakbesturingssoftware. Wanneer een browser een pagina rendert, bouwt hij twee parallelle structuren op: de DOM (wat je ziet) en de Accessibility Tree (wat ondersteunende technologieën lezen). ARIA-attributen laten je die Accessibility Tree aanpassen om nauwkeurig te beschrijven wat custom componenten zijn en hoe ze zich gedragen.

De noodzaak voor ARIA is ontstaan uit een reëel probleem. HTML is ontworpen voor documenten, niet voor applicaties. Toen het web evolueerde tot een platform voor rijke, interactieve ervaringen — tabinterfaces, modale dialogen, drag-and-drop, live datafeeds — konden native HTML-elementen niet overbrengen wat die componenten waren of hoe ze werkten voor een schermlezer. ARIA vult dat gat. Zoals MDN het verwoordt, ARIA "supplements HTML so that interactions and widgets commonly used in applications can be passed to assistive technologies when there is not otherwise a mechanism."

ARIA verandert de visuele presentatie niet. Het voegt geen gedrag toe. Het biedt niet automatisch toetsenbordondersteuning. Het wijzigt puur wat de Accessibility Tree blootlegt aan ondersteunende technologie. Dit is een belangrijk onderscheid — en een van de oorzaken van veel fouten die ontwikkelaars maken wanneer ze ARIA als een shortcut inzetten.

De specificatie wordt door het W3C onderhouden als WAI-ARIA, momenteel versie 1.2, met 1.3 actief in ontwikkeling. Ze biedt een ontologie van rollen, statussen en eigenschappen die samen toegankelijke gebruikersinterface-elementen beschrijven voor het volledige spectrum aan moderne webpatronen.

De Drie Pijlers: Rollen, Statussen en Eigenschappen

Voordat je ook maar één regel ARIA schrijft, moet je de drie verschillende bouwstenen begrijpen die de specificatie biedt. Ze zijn niet uitwisselbaar, en ze door elkaar halen is een van de meest voorkomende bronnen van fouten.

Rollen definiëren wat een element is. Een rol beantwoordt de vraag: naar wat voor soort ding kijk ik? Voorbeelden zijn button, dialog, navigation, tablist en progressbar. Je past een rol toe met het role-attribuut: <div role='button'>. De rol communiceert het doel van het element aan ondersteunende technologie zodat de gebruiker weet hoe ermee te interageren.

Statussen beschrijven de dynamische toestand van een element — iets dat verandert terwijl de gebruiker met de pagina interageert. Het attribuut aria-expanded vertelt een schermlezer of een uitklapbaar gedeelte open of gesloten is. aria-checked geeft weer of een custom checkbox aangevinkt is. Statussen moeten synchroon worden gehouden met JavaScript; een statische aria-expanded='false' die nooit verandert is niet alleen nutteloos maar actief misleidend.

Eigenschappen bieden beschrijvende, meestal stabielere informatie over een element. aria-label geeft een element een toegankelijke naam die de zichtbare tekst overschrijft. aria-labelledby verwijst naar een ander element waarvan de tekst als label dient. aria-describedby koppelt aanvullende beschrijvende tekst. aria-required geeft aan dat een formulierveld verplicht is. Terwijl statusssen naar verwachting vaak veranderen, worden eigenschappen meestal één keer ingesteld en vervolgens met rust gelaten — al zijn er uitzonderingen.

Rollen definiëren wat een element is. Statussen definiëren hoe het zich op dit moment gedraagt. Eigenschappen bieden aanvullende beschrijvende context. Je hebt alle drie nodig, die samen werken, om een volledig toegankelijk custom component te maken.

De Gouden Regel — en Waarom Die Meer Betekent Dan Je Denkt

De eerste regel van het W3C voor ARIA-gebruik is ondubbelzinnig: als je een native HTML-element of -attribuut kunt gebruiken met de semantiek en het gedrag die je nodig hebt al ingebouwd, gebruik dat dan. Grijp niet als eerste naar ARIA. Dit wordt soms het "no ARIA is better than bad ARIA"-principe genoemd — een uitdrukking die het zeer reële gevaar weerspiegelt van goedbedoeld maar incorrect ARIA-gebruik.

Native HTML-elementen dragen impliciete ARIA-semantieken gratis mee. Een <button>-element wordt al als button blootgelegd aan de Accessibility Tree. Het is al met het toetsenbord te focussen. Het reageert al op zowel Enter- als Spatie-toets. Het kondigt zijn label al aan. Op het moment dat je <div role='button'> schrijft, neem je de verantwoordelijkheid op je om al dat gedrag handmatig te reproduceren — de toetsenbordafhandeling, de focusmanagement, de statusupdates — in JavaScript. Dit is geen theoretische zorg. Toetsenbordondersteuning vergeten bij een custom button is een van de meest voorkomende en meest schadelijke ARIA-fouten in productie.

De gevallen waarin ARIA echt noodzakelijk is, clusteren meestal rond een paar scenario’s: wanneer je een complex widget bouwt dat geen HTML-equivalent heeft (een carrousel, een combobox met autocomplete, een boomstructuur); wanneer je legacy-markup aan het herstellen bent waarbij het herstructureren van de DOM te kostbaar is; wanneer je een webcomponent bouwt die custom semantiek moet blootleggen; of wanneer browser- en ondersteunende-technologie-ondersteuning voor een native element zo inconsistent is dat het ARIA-equivalent in de praktijk betrouwbaarder werkt.

Buiten die scenario’s zou je eerste instinct altijd semantische HTML moeten zijn. Gebruik <nav> in plaats van <div role='navigation'>. Gebruik <main> in plaats van <div role='main'>. Gebruik <button> in plaats van <div role='button'>. De native elementen zijn robuuster, beter ondersteund en vereisen veel minder onderhoud.

Een Rondleiding Langs de Belangrijkste ARIA-rolcategorieën

De WAI-ARIA-specificatie organiseert rollen in verschillende categorieën. Inzicht in deze categorieën helpt je te weten naar welke rol je moet grijpen en wanneer.

Landmark-rollen

Landmark-rollen markeren de belangrijkste regio’s van een pagina, zodat schermlezergebruikers met sneltoetsen direct naar belangrijke secties kunnen springen. De meest gebruikte landmark-rollen zijn banner, navigation, main, complementary, contentinfo, search en form. Voor elk hiervan bestaat een direct native HTML-equivalent: <header>, <nav>, <main>, <aside>, <footer>, enzovoort. In de praktijk betekent dit dat landmark-rollen bijna altijd overbodig zijn als je moderne semantische HTML gebruikt. Voeg ze alleen toe wanneer je om structurele redenen vastzit aan niet-semantische markup.

<!-- Prefer this -->
<header>
  <nav>...</nav>
</header>
<main>...</main>
<footer>...</footer>

<!-- Use ARIA only when you must use divs -->
<div role='banner'>
  <div role='navigation'>...</div>
</div>
<div role='main'>...</div>
<div role='contentinfo'>...</div>

Widget-rollen

Widget-rollen beschrijven interactieve componenten die de gebruiker direct bedient. Dit is waar ARIA zijn belangrijkste werk doet, omdat veel widgetpatronen geen native HTML-equivalent hebben. Veelvoorkomende widget-rollen zijn button, checkbox, dialog, menu, menuitem, slider, tablist, tab, tabpanel, tooltip, tree en combobox.

Wanneer je een widget-rol gebruikt, neem je de volledige verantwoordelijkheid voor toetsenbordinteractie. De WAI-ARIA Authoring Practices Guide (APG) definieert verwachte toetsenbordpatronen voor elk type widget — bijvoorbeeld pijltjestoetsen om tussen tabs te bewegen, Escape om een dialoog te sluiten, Home en End om naar het eerste en laatste item in een listbox te springen. Als je deze patronen niet implementeert, is je component technisch gelabeld maar functioneel onbruikbaar voor gebruikers die alleen het toetsenbord gebruiken.

<!-- A custom tab interface -->
<div role='tablist' aria-label='Account settings'>
  <button role='tab' aria-selected='true' aria-controls='panel-profile' id='tab-profile'>
    Profile
  </button>
  <button role='tab' aria-selected='false' aria-controls='panel-security' id='tab-security' tabindex='-1'>
    Security
  </button>
</div>
<div role='tabpanel' id='panel-profile' aria-labelledby='tab-profile'>
  <p>Profile settings content</p>
</div>
<div role='tabpanel' id='panel-security' aria-labelledby='tab-security' hidden>
  <p>Security settings content</p>
</div>

Live region-rollen

Live regions zijn een van de meest echt nuttige features van ARIA. Ze stellen ondersteunende technologieën in staat om dynamische contentupdates — dingen als statusberichten, foutmeldingen, chatberichten en laadindicatoren — aan te kondigen aan gebruikers die de schermverandering niet kunnen zien. Zonder live regions zou een schermlezergebruiker die een formulier verstuurt misschien nooit weten of het gelukt of mislukt is, tenzij de focus expliciet naar het resultaat wordt verplaatst.

De kern-live-region-rollen zijn alert, status, log, marquee en timer. De rol alert heeft impliciet de instelling aria-live='assertive', wat betekent dat hij de gebruiker onmiddellijk onderbreekt — passend voor fouten of dringende waarschuwingen. De rol status gebruikt aria-live='polite', wachtend tot de gebruiker zijn huidige taak heeft afgerond voordat er wordt aangekondigd — ideaal voor succesberichten en voortgangsindicatoren.

<!-- Polite status message for non-urgent feedback -->
<div role='status' aria-live='polite' aria-atomic='true'>
  <!-- Dynamically inject text here with JavaScript -->
</div>

<!-- Assertive alert for errors that demand immediate attention -->
<div role='alert'>
  Please correct the errors below before submitting.
</div>

De sleutel tot live regions is dat de container al in de DOM aanwezig moet zijn voordat de dynamische content wordt ingevoegd. Een live region die tegelijkertijd wordt aangemaakt en gevuld, wordt vaak gemist door schermlezers. Bouw de container bij het laden van de pagina en vul hem met JavaScript terwijl events plaatsvinden.

Documentstructuur-rollen

Documentstructuur-rollen — zoals article, list, listitem, table, row, cell, figure en heading — beschrijven de structurele organisatie van content. De meeste hiervan zijn inmiddels vervangen door native HTML-elementen, en MDN merkt op dat het merendeel van de documentstructuur-rollen "should no longer be used as browsers now support semantic HTML elements with the same meaning." De belangrijkste uitzondering is wanneer je werkt met custom renderomgevingen, webcomponents of op SVG gebaseerde content waar native HTML-elementen niet beschikbaar zijn.

Essentiële ARIA-eigenschappen Die Elke Ontwikkelaar Moet Kennen

Naast rollen komen verschillende ARIA-eigenschappen voortdurend terug in toegankelijkheidswerk in de praktijk. Dit zijn degene waar je het vaakst naar zult grijpen:

  • aria-label: Biedt een toegankelijke naam voor een element wanneer er geen zichtbaar tekstlabel beschikbaar is of wanneer de zichtbare tekst onvoldoende is. Veelvoorkomende use-cases: knoppen die alleen uit een icoon bestaan, zoekvelden zonder zichtbaar label en sluitknoppen op modals. Let op: aria-label overschrijft elke zichtbare tekst of native label, dus gebruik het voorzichtig op elementen die wel zichtbare tekst hebben.
  • aria-labelledby: Verwijst naar één of meer elementen waarvan de tekstinhoud als toegankelijke naam dient. Robuuster dan aria-label voor complexe gevallen omdat de labeltekst gesynchroniseerd blijft met de zichtbare content. Accepteert een door spaties gescheiden lijst van element-ID’s, en ondersteunende technologieën concatenëren de gerefereerde tekst in volgorde.
  • aria-describedby: Verbindt aanvullende beschrijvingstekst — geen naam, maar extra context. Gebruik het om formuliervelden te koppelen aan hun foutmeldingen, of om een tooltip te associëren met het element dat het beschrijft. Schermlezers kondigen dit meestal aan na de naam en rol van het element.
  • aria-hidden: Verwijdert een element volledig uit de Accessibility Tree. Onschatbaar voor decoratieve iconen, dubbele content en puur visuele elementen die ruis zouden creëren voor schermlezergebruikers. Pas nooit aria-hidden='true' toe op een focusbaar element — een gebruiker kan er nog steeds naartoe tabben, maar krijgt er geen informatie over.
  • aria-expanded: Communiceert of een uitklapbaar element — een dropdown, accordion of disclosure-widget — momenteel open of gesloten is. Moet dynamisch met JavaScript worden omgeschakeld; een statische waarde is slechter dan het attribuut helemaal weglaten.
  • aria-current: Geeft het huidige item binnen een set aan, meestal gebruikt voor navigatie om de actieve paginalink te markeren (aria-current='page') of de huidige stap in een meerstapsproces.

Veelvoorkomende ARIA-fouten Die Toegankelijkheid Echt Schaden

Aangezien pagina’s met ARIA de neiging hebben meer toegankelijkheidsfouten te vertonen dan die zonder, is het de moeite waard expliciet te zijn over wat het vaakst misgaat. Dit zijn geen randgevallen — het zijn patronen die elke dag in productiecode opduiken.

ARIA-rollen gebruiken op elementen met sterke native semantiek. Sommige HTML-elementen hebben wat de specificatie "strong native semantics" noemt — betekenissen die diep in de browser zijn ingebakken en niet veilig kunnen worden overschreven. Een ongeschikte rol plaatsen op een <button> of een <input> kan ertoe leiden dat de browser de ARIA-rol volledig negeert, of tegenstrijdig gedrag produceert dat ondersteunende technologieën in verwarring brengt. De rol die je declareert moet passend zijn voor het element waarop je hem zet.

Toetsenbordondersteuning vergeten bij widget-rollen. ARIA’s role='button' vertelt een schermlezer dat het element een button is. Het maakt het element niet toetsenbordbedienbaar. Als je een <div> met role='button' gebruikt, moet je tabindex='0' toevoegen om het focusbaar te maken, en je moet eventlisteners toevoegen voor zowel de Enter- als de Spatie-toets. Als een van deze onderdelen ontbreekt, breek je de ervaring voor gebruikers die alleen het toetsenbord gebruiken.

<!-- Incomplete and inaccessible -->
<div role='button' onclick='doSomething()'>Submit</div>

<!-- Correct custom button implementation -->
<div
  role='button'
  tabindex='0'
  onclick='doSomething()'
  onkeydown='if(event.key==="Enter"||event.key===" ")doSomething()'
>Submit</div>

<!-- Or, the right answer: just use a button -->
<button onclick='doSomething()'>Submit</button>

aria-hidden gebruiken op focusbare elementen. aria-hidden='true' toepassen op een focusbaar element verbergt het in de Accessibility Tree maar niet voor toetsenbordnavigatie. Een toetsenbordgebruiker kan er nog steeds naartoe tabben, krijgt er geen informatie over en heeft geen manier om te weten wat het doet. Dit is een WCAG 2.1-fout onder Succescriterium 4.1.2 (Name, Role, Value).

Verouderde ARIA-statussen. Het niet bijwerken van aria-expanded, aria-checked, aria-selected en vergelijkbare statussen wanneer de UI verandert, laat schermlezergebruikers achter met een fundamenteel onjuist beeld van de interface. Een menu dat visueel opent maar waarvan de trigger nog steeds aria-expanded='false' aangeeft, is actief misleidend.

Redundante rollen. role='navigation' toevoegen aan een <nav>-element, of role='button' aan een <button>, doet niets nuttigs. Het vervuilt de code en kan af en toe bepaalde combinaties van ondersteunende technologie in verwarring brengen. Vertrouw op de native semantiek.

ARIA en WCAG: Het Verband Begrijpen

ARIA is niet WCAG. Het zijn aparte specificaties die samenwerken. WCAG (Web Content Accessibility Guidelines) definieert het wat — de resultaten die vereist zijn voor toegankelijke content. ARIA is onderdeel van het hoe — een technische mechanisme om sommige van die resultaten te bereiken. Het meest relevante WCAG-succescriterium voor ARIA is 4.1.2: Name, Role, Value, dat vereist dat alle gebruikersinterfacecomponenten een naam hebben, hun rol blootleggen aan ondersteunende technologieën en hun status en eigenschappen programmatisch communiceren. ARIA is een van de belangrijkste tools om aan dit criterium te voldoen voor custom componenten.

ARIA ondersteunt ook verschillende andere succescriteria. Landmark-rollen dragen bij aan 2.4.1 (Bypass Blocks) door skip-navigatie mogelijk te maken. Live regions zijn vaak het juiste middel om te voldoen aan 4.1.3 (Status Messages) in WCAG 2.1, dat vereist dat statusberichten programmatisch bepaalbaar zijn zonder focus te krijgen. Correct gebruik van aria-label en aria-labelledby helpt om te voldoen aan 2.4.6 (Headings and Labels) en 1.3.1 (Info and Relationships).

Het is vermeldenswaard dat WCAG-naleving in toenemende mate een wettelijke vereiste is. De European Accessibility Act is in juni 2025 volledig in werking getreden en breidt verplichte toegankelijkheidseisen uit naar een breed scala aan digitale diensten in de private sector in EU-lidstaten. In de Verenigde Staten wordt de ADA steeds vaker geïnterpreteerd als inclusief webtoegankelijkheid, en federale vereisten onder Section 508 zijn van toepassing op overheids- en door de federale overheid gefinancierde organisaties. ARIA correct begrijpen is niet alleen best practice — het is in toenemende mate onderdeel van je complianceverplichtingen.

Je ARIA-implementatie Testen

De enige manier om te weten of je ARIA-implementatie daadwerkelijk werkt, is door deze te testen met echte ondersteunende technologieën. Geautomatiseerde tools zoals axe, WAVE en Lighthouse kunnen structurele overtredingen opsporen — een ontbrekende vereiste eigenschap, een ongeldige rol, een aria-hidden toegepast op een focusbaar element — maar ze kunnen je niet vertellen of een schermlezer je modal op een begrijpelijke manier aankondigt, of dat toetsenbordnavigatie door je custom tree-widget de verwachte patronen volgt.

Voor handmatige tests zijn de belangrijkste schermlezers om te dekken JAWS en NVDA op Windows (samen vertegenwoordigen ze het overgrote deel van het desktopgebruik van schermlezers), en VoiceOver op macOS en iOS. TalkBack dekt Android. Elke combinatie van schermlezer en browser kan zich anders gedragen, dus testen met minstens twee combinaties wordt sterk aanbevolen. Test elke interactieve status: open de dialoog, klap de accordion uit, selecteer de optie, trigger de alert. Bevestig dat de aankondiging overeenkomt met wat een ziende gebruiker zou begrijpen door naar dezelfde interface te kijken.

Wanneer je custom widgets test, doorloop dan het toetsenbordinteractiemodel dat in de WAI-ARIA Authoring Practices Guide is gedefinieerd voor dat type widget. Als je tablist niet reageert op pijltjestoetsen, of je dialoog de focus niet vastzet, zijn dat fouten ongeacht hoe correct de ARIA-markup eruitziet in een geautomatiseerde audit.

Belangrijkste Punten om te Onthouden

  • Geef altijd de voorkeur aan semantische HTML boven ARIA. Native elementen zoals <button>, <nav>, <main> en <dialog> hebben ingebouwde toegankelijkheidssemantiek die robuuster is en veel minder code vereist dan hun ARIA-op-een-div-equivalenten. Grijp pas naar ARIA wanneer native HTML echt tekortschiet.
  • ARIA-rollen zijn een belofte, geen shortcut. role='button' of role='dialog' toepassen op een custom element verplicht je om het volledige toetsenbordinteractiemodel voor dat type widget te implementeren. Rollen zonder bijpassend gedrag creëren verwarring en WCAG-fouten.
  • Houd ARIA-statussen gesynchroniseerd met je UI. Dynamische attributen zoals aria-expanded, aria-checked, aria-selected en aria-live-content moeten in JavaScript worden bijgewerkt wanneer de UI verandert. Een verouderde status is actief schadelijk — hij communiceert de verkeerde informatie aan de gebruiker.
  • Gebruik live regions voor dynamische contentupdates. Alle content die wordt bijgewerkt zonder paginareload — notificaties, foutmeldingen, laadstatussen, chatfeeds — heeft een aria-live-region of een passende rol zoals alert of status nodig zodat schermlezergebruikers dezelfde informatie automatisch ontvangen als ziende gebruikers.
  • Test met echte ondersteunende technologieën, niet alleen met geautomatiseerde tools. Geautomatiseerde scanners sporen structurele ARIA-fouten op maar kunnen niet valideren of je implementatie een samenhangende, bruikbare ervaring oplevert. Handmatig testen met JAWS, NVDA en VoiceOver is de enige manier om dat gat te dichten.