Als je een website gebruikt zonder dat je het scherm kunt zien. Hoe weet je dan:
- Welke tekst een kop is en welk niveau deze heeft?
- Welke items bij elkaar horen in een lijst?
- Welke cellen bij welke rijen of kolommen horen in een tabel?
Als je alleen visuele opmaak gebruikt (zoals vetgedrukte tekst of grotere lettertypen) zonder semantische HTML, dan mist een gebruiker van een schermlezer deze structuur.
Wat is WCAG 1.3.1 eigenlijk?
Succescriterium 1.3.1 Info en relaties is een van de belangrijke WCAG-succescriteria. Het criterium stelt:
Informatie, structuur en relaties overgebracht door presentatie kunnen door software bepaald worden of zijn beschikbaar in tekst.
Simpel gezegd: Alle informatie, structuur en relaties die iemand visueel kan waarnemen, moeten ook in de code worden vastgelegd. Hierdoor zijn deze ook beschikbaar voor mensen die hulptechnologieën gebruiken, zoals een schermlezer. En dat is precies waar semantische HTML in beeld komt.
Waarom semantische HTML zo belangrijk is
Semantische HTML gebruikt elementen in de code die betekenis geven aan je content, in plaats van alleen te focussen op hoe het eruit ziet.
Vergelijk deze twee voorbeelden:
<!-- Niet-semantisch -->
<div class="title">Mijn hoofdkop</div>
<div class="subtitle">Mijn subkop</div>
<!-- Semantisch -->
<h1>Mijn hoofdkop</h1>
<h2>Mijn subkop</h2>
Voor een iemand die goed kan zien is er misschien geen verschil als je de juiste CSS toepast, maar voor een schermlezer is er wél verschil. In het semantische voorbeeld weet hulptechnologie dat het met koppen te maken heeft en wat hun onderlinge hiërarchie is.
Koppen
Laten we beginnen met koppen. Deze zijn ontzettend belangrijk voor de structuur van je pagina.
Waarom goede koppen belangrijk zijn
Koppen zorgen voor:
- Context voor de inhoud die volgt
- Navigatiepunten voor gebruikers van een schermlezer
Wist je dat mensen die een schermlezer gebruiken vaak navigeren door de koppen op een pagina? Door op één toets te drukken kunnen ze door van kop naar kop springen. Als je kopstructuur niet klopt, dan is dat alsof je de inhoudsopgave van een boek helemaal door elkaar haalt.
In de Rotor van VoiceOver ziet dit er zo uit:

Best practices voor koppen
Vermijd zo veel mogelijk het overslaan van kopniveaus. Ga van h1 naar h2 naar h3 en spring dus niet van h1 naar h3.
<!-- Slecht voorbeeld -->
<h1>Productoverzicht</h1>
<h3>Elektronica</h3> <!-- Sprong van h1 naar h3 -->
<h6>Smartphones</h6> <!-- Sprong van h3 naar h6 -->
<!-- Goed voorbeeld -->
<h1>Productoverzicht</h1>
<h2>Elektronica</h2>
<h3>Smartphones</h3>
<h3>Laptops</h3>
<h2>Kleding</h2>
<h3>Dames</h3>
<h3>Heren</h3>
Begin de content van elke pagina met een h1 en zorg dat deze kop de inhoud van de pagina beschrijft.
Veelgemaakte fouten
- Tekst die een kop is, wordt in de code niet opgemaakt met een kop-element
- Kop-elementen worden gebruikt alleen maar omdat ze er “mooi” uitzien (voor het ontwerp of de stijl)
- Kopniveaus worden overgeslagen waardoor dit de betekenis van de content in de weg zit
<!-- Slecht voorbeeld -->
<div class="heading">Belangrijke sectie</div>
<!-- Goed voorbeeld -->
<h2>Belangrijke sectie</h2>
Lijsten
Lijsten maken je tekst makkelijker te lezen en te begrijpen.
Soorten lijsten
Er zijn drie soorten lijsten om gerelateerde items te groeperen en hiërarchie aan te brengen:
- Ongeordende lijst of opsomming
- Geordende of genummerde lijst
- Definitielijst
<!-- Ongeordende lijst -->
<ul>
<li>Appels</li>
<li>Bananen</li>
<li>Peren</li>
</ul>
<!-- Geordende lijst -->
<ol>
<li>Meng de ingrediënten</li>
<li>Bak het deeg</li>
<li>Laat het afkoelen</li>
</ol>
<!-- Definitielijst -->
<dl>
<dt>HTML</dt>
<dd>HyperText Markup Language, de standaardtaal voor webpagina's</dd>
<dt>CSS</dt>
<dd>Cascading Style Sheets, voor de opmaak van webpagina's</dd>
</dl>
Schermlezers kondigen het type lijst aan en ook het aantal items in de lijst. Hierdoor weet de gebruiker wat te verwachten.
Veelgemaakte fouten
- Tekst wordt geplaatst met handmatige opsommingstekens of nummering
- Geneste lijsten worden niet juist gestructureerd
<!-- Slecht voorbeeld -->
<div>- Eerste item</div>
<div>- Tweede item</div>
<div>- Derde item</div>
<!-- Goed voorbeeld -->
<ul>
<li>Eerste item</li>
<li>Tweede item</li>
<li>Derde item</li>
</ul>
Een tip: als je visuals gebruikt voor je bullets via CSS, zorg dan dat je nog steeds de semantische lijst-elementen behoudt. Je kunt list-style: none gebruiken en dan je eigen bullets toevoegen met CSS.
Tabellen
Tabellen gebruik je om gegevens te presenteren of te vergelijken. Tabellen worden vaak verkeerd gebruikt. Ze zijn echt bedoeld voor tabulaire gegevens, en dus niet voor layout.
Een toegankelijke tabel maken
Een toegankelijke tabel heeft altijd:
<th>: Tabelkoppen (metscope-attribuut)<td>: Tabeldata (cellen)<caption>: Beschrijft waar de tabel over gaat<thead>,<tbody>,<tfoot>: Structureren de tabel in logische secties
<table>
<caption>Aantal succescriteria per WCAG niveau</caption>
<thead>
<tr>
<th scope="col">WCAG versie</th>
<th scope="col">Niveau A</th>
<th scope="col">Niveau AA</th>
<th scope="col">Niveau AAA</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">WCAG 2.1</th>
<td>30</td>
<td>50</td>
<td>78</td>
</tr>
<tr>
<th scope="row">WCAG 2.2</th>
<td>30</td>
<td>54</td>
<td>86</td>
</tr>
</tbody>
</table>
Het scope-attribuut is belangrijk. Het vertelt hulptechnologie of een tabelkop bij een rij of kolom hoort. Gebruik dit attribuut altijd als er koppen in twee richtingen zijn. Gebruik de waarde col voor kolom en row voor rij.
Complexe tabellen
Voor complexere tabellen kun je headers en id gebruiken:
<table>
<caption>Kwartaalcijfers per afdeling</caption>
<tr>
<td></td>
<th id="q1">Kwartaal 1</th>
<th id="q2">Kwartaal 2</th>
<th id="q3">Kwartaal 3</th>
<th id="q4">Kwartaal 4</th>
</tr>
<tr>
<th id="sales">Verkoop</th>
<td headers="sales q1">€10K</td>
<td headers="sales q2">€12K</td>
<td headers="sales q3">€15K</td>
<td headers="sales q4">€18K</td>
</tr>
<tr>
<th id="marketing">Marketing</th>
<td headers="marketing q1">€5K</td>
<td headers="marketing q2">€6K</td>
<td headers="marketing q3">€7K</td>
<td headers="marketing q4">€8K</td>
</tr>
</table>
Door de headers-attributen kan een schermlezer hier aankondigen: “Verkoop Kwartaal 1 €10K”. Zo weet de gebruiker dus precies welke gegevens ze horen.
Veelgemaakte fouten
- Tabellen worden gebruikt voor de opmaak van een pagina
- Datatabellen zonder tabelkoppen
<!-- Slecht voorbeeld -->
<table>
<tbody>
<tr>
<th scope="row">Januari</th>
<td>€750</td>
<td>€300</td>
<td>€1050</td>
</tr>
<tr>
<th scope="row">Februari</th>
<td>€750</td>
<td>€280</td>
<td>€1030</td>
</tr>
</tbody>
</table>
<!-- Goed voorbeeld -->
<table>
<caption>Maandelijkse uitgaven</caption>
<thead>
<tr>
<th scope="col">Maand</th>
<th scope="col">Huur</th>
<th scope="col">Eten</th>
<th scope="col">Totaal</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Januari</th>
<td>€750</td>
<td>€300</td>
<td>€1050</td>
</tr>
<tr>
<th scope="row">Februari</th>
<td>€750</td>
<td>€280</td>
<td>€1030</td>
</tr>
</tbody>
</table>
Praktische tips voor het testen
Om je implementatie te controleren:
- Schakel je CSS uit: Is je content nog steeds logisch en begrijpelijk?
- Controleer je kopstructuur: Beschrijft het hoofdlijnen de inhoud van de pagina?
- Gebruik zelf eens een schermlezer: NVDA (Windows) of VoiceOver (Mac) zijn goede opties
- Gebruik de Web Developer Toolbar: Om HTML-elementen te markeren
Conclusie
Semantische HTML is geen extra werk maar eigenlijk de enige juiste manier van ontwikkelen.
Heb je vragen over specifieke implementaties? Laat het me weten!