Info en relaties en semantische HTML

Stel je eens voor dat 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 bieden:

  1. Een hiërarchische structuur van de pagina
  2. Context voor de inhoud die volgt
  3. 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.

Best practices voor koppen

Vermijd 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 ph3! -->
<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 als kop
  • Kop-elementen worden gebruikt voor het ontwerp of de stijl (omdat ze er “mooi” uitzien)
  • 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 -->
<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 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:

  • <caption>: Beschrijft waar de tabel over gaat
  • <thead><tbody><tfoot>: Structureren de tabel in logische secties
  • <th>: Tabelkoppen (met scope-attribuut)
  • <td>: Tabeldata (cellen)
<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>

Het scope-attribuut is belangrijk. Het vertelt hulptechnologie of een kop bij een rij of kolom hoort.

Complexe tabellen

Voor complexere tabellen kun je headers en id gebruiken:

<table>
  <caption>Kwartaalcijfers per afdeling</caption>
  <tr>
    <td></td>
    <th id="q1">Q1</th>
    <th id="q2">Q2</th>
    <th id="q3">Q3</th>
    <th id="q4">Q4</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 Q1: €10K” – zo weet de gebruiker precies welke gegevens ze horen.

Veelgemaakte fouten

  • Tabellen worden gebruikt voor de opmaak van een pagina
  • Datatabellen worden gebruikt zonder tabelkoppen
  • Er wordt geen beschrijving toegevoegd aan datatabellen
<!-- Slecht voorbeeld -->
<table>
  <tr>
    <td>Logo</td>
    <td>Navigatie</td>
  </tr>
  <tr>
    <td>Zijbalk</td>
    <td>Content</td>
  </tr>
</table>

<!-- Goed voorbeeld -->
<header>
  <div class="logo">Logo</div>
  <nav>Navigatie</nav>
</header>
<div class="container">
  <aside>Zijbalk</aside>
  <main>Content</main>
</div>

ARIA: Alleen als HTML niet genoeg is

Soms heb je complexe UI-elementen waarvoor de standaard HTML-semantiek niet helemaal toereikend is. Dan komt ARIA (Accessible Rich Internet Applications) van pas. Maar onthoud altijd de eerste regel van ARIA: Gebruik geen ARIA als je native HTML-elementen kunt gebruiken!

Een voorbeeld van wanneer ARIA nuttig kan zijn:

<!-- Een tab-interface -->
<div role="tablist">
  <button role="tab" aria-selected="true" aria-controls="panel1" id="tab1">Tab 1</button>
  <button role="tab" aria-selected="false" aria-controls="panel2" id="tab2">Tab 2</button>
</div>

<div id="panel1" role="tabpanel" aria-labelledby="tab1">
  Content van tab 1
</div>
<div id="panel2" role="tabpanel" aria-labelledby="tab2" hidden>
  Content van tab 2
</div>

Praktische tips voor het testen

Om je implementatie te controleren:

  1. Schakel je CSS uit: Is je content nog steeds logisch en begrijpelijk?
  2. Controleer je kopstructuur: Beschrijft het hoofdlijnen de inhoud van de pagina?
  3. Gebruik zelf eens een schermlezer: NVDA (Windows) of VoiceOver (Mac) zijn goede opties
  4. Gebruik de Web Developer Toolbar: Om HTML-elementen te markeren

Lees meer over hulpmiddelen

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!