Als je voor alles <div> hebt gebruikt — paginawrapper, navigatie, artikelcontainer, sidebar — ben je niet de enige. Het was jarenlang de standaardkeuze. Maar HTML heeft al sinds HTML5 echte semantische elementen, en ze gebruiken maakt je code leesbaarder, beter voor SEO en echt toegankelijker. Laten we de elementen bespreken die er echt toe doen.
Het woord "semantisch" betekent eenvoudigweg dat het element betekenis heeft naast zijn visuele presentatie. Een <div> betekent niets — het is een generiek blok. Een <nav> vertelt de browser, zoekmachines en hulptechnologie: "dit bevat navigatielinks." Die context kost niets om toe te voegen en levert op meerdere manieren voordeel op.
Waarom Semantiek Belangrijk Is
Drie echte voordelen, geen theoretische:
- SEO. Zoekmachines gebruiken de documentstructuur om de inhoudshiërarchie te begrijpen. Een
<main>-element signaleert de primaire inhoud. Een<article>erin signaleert een op zichzelf staand stuk. Google gebruikt deze signalen bij het rangschikken van pagina's. - Toegankelijkheid. Schermlezers stellen landmarkgebieden bloot aan gebruikers. Met
<nav>,<main>en<aside>aanwezig, kunnen toetsenbordgebruikers direct naar de gewenste sectie springen — zonder door elke link op de pagina te tabben. - Onderhoudbaarheid. Een nieuwe ontwikkelaar die jouw template leest, begrijpt de paginastructuur meteen.
<header>/<main>/<footer>documenteert zichzelf op een manier die<div class="top">/<div class="content">/<div class="bottom">niet doet.
De Kern Layout-elementen
Deze vijf elementen verzorgen het buitenste skelet van de meeste pagina's. Gebruik ze op elke pagina en je hebt al de helft van de semantische strijd gewonnen:
<body>
<header>
<a href="/" class="logo">MyBlog</a>
<nav>
<ul>
<li><a href="/articles">Articles</a></li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav>
</header>
<main>
<!-- Primary page content goes here -->
</main>
<aside>
<!-- Sidebar: related links, ads, author bio -->
</aside>
<footer>
<p>© 2026 MyBlog. All rights reserved.</p>
</footer>
</body><header>. Inleidende inhoud voor de pagina of een sectie. Bevat gewoonlijk het logo, de sitetitel en de primaire navigatie. Je kunt het ook gebruiken binnen een<article>voor het eigen kopblok van een artikel.<nav>. Een set navigatielinks. Niet elke groep links heeft een<nav>nodig — gebruik het voor grote navigatieblokken zoals de sitenavigatie of paginering.<main>. De dominante inhoud van de pagina. Er mag slechts één<main>per pagina zijn en het mag niets bevatten dat over pagina's herhaald wordt (header, nav, footer).<aside>. Inhoud die zijdelings gerelateerd is aan de hoofdinhoud. Zijbalken, uitgelichte citaten, gerelateerde artikelen. Schermlezers stellen dit bloot als een aanvullend landmark.<footer>. Footer voor de pagina of een sectie. Kan copyrightinformatie, secundaire navigatie, contactlinks of een korte auteursnotitie bevatten.
<header> en <footer> zijn niet beperkt tot het paginaniveau. Elk <article> of <section> kan zijn eigen <header> en <footer> hebben. Dit is met name handig voor auteursvermeldingen bij blogposts en metadata op artikelniveau.article vs section — Wanneer Gebruik je Welk
Dit is de vraag die de meeste mensen struikelblok doet. De vuistregel die echt werkt: als de inhoud zinvol zou zijn als je het zelfstandig publiceert (bijv. als RSS-item of gedeeld op een andere site), is het een <article>. Als het alleen zinvol is als deel van een groter geheel, is het een <section>.
<!-- article: self-contained, could stand alone -->
<article>
<header>
<h2>Understanding HTTP/2 Push</h2>
<p>By Alice Chen — <time datetime="2026-03-15">March 15, 2026</time></p>
</header>
<p>HTTP/2 Server Push lets the server send resources...</p>
<footer>
<p>Tagged: <a href="/tags/http">HTTP</a>, <a href="/tags/performance">Performance</a></p>
</footer>
</article>
<!-- section: thematic grouping within a page -->
<section>
<h2>Related Articles</h2>
<ul>
<li><a href="/http3-quic">HTTP/3 and QUIC Explained</a></li>
<li><a href="/cdn-strategy">CDN Strategy for Global Apps</a></li>
</ul>
</section><section> zou altijd een kop moeten hebben (van <h2> tot <h6>). Als je sectie geen kop heeft, is dat meestal een teken dat je een <div> zou moeten gebruiken. De WHATWG-specificatie is hierover duidelijk: <section> is voor thematische groeperingen, niet voor willekeurige lay-outindelingen.
figure, figcaption, time en address
Vier elementen die ontwikkelaars vaak over het hoofd zien maar regelmatig nodig hebben:
<!-- figure + figcaption: images, code blocks, diagrams, charts -->
<figure>
<img src="/images/latency-chart.png" alt="P99 latency over 24 hours showing a spike at 14:30">
<figcaption>Figure 1: API latency during the Tuesday incident (UTC).</figcaption>
</figure>
<!-- A code block as a figure (totally valid) -->
<figure>
<pre><code>const result = await db.query('SELECT * FROM users WHERE active = true');</code></pre>
<figcaption>Listing 1: Basic active user query.</figcaption>
</figure>
<!-- time: machine-readable dates and times -->
<p>Published <time datetime="2026-04-16T09:00:00Z">April 16, 2026</time></p>
<p>Sale ends in <time datetime="PT2H30M">2 hours 30 minutes</time></p>
<!-- address: contact info for nearest article or body ancestor -->
<address>
Written by <a href="mailto:[email protected]">Alice Chen</a>.<br>
123 Dev Street, San Francisco, CA.
</address><figure>. Elke op zichzelf staande inhoud waarnaar vanuit de hoofdstroom wordt verwezen — afbeeldingen, codeoverzichten, grafieken, video's. Het kernpunt: het kan naar een bijlage worden verplaatst zonder de leesstroom te verstoren.<figcaption>. Het bijschrift voor een<figure>. Moet het eerste of laatste kind van<figure>zijn. Geeft een semantische associatie tussen het bijschrift en de inhoud die een<p>onder een afbeelding niet biedt.<time>. Mensvriendelijke datums met een machineleesbaardatetime-attribuut. Dedatetime-waarde gebruikt het ISO 8601-formaat. Zoekmachines gebruiken dit voor event markup en versheidsignalen.<address>. Contactinformatie voor de dichtstbijzijnde<article>-voorouder (of het hele<body>). Geen algemeen adreselement — het is specifiek voor de contactgegevens van de inhoudsauteur of site-eigenaar.
Het Divitis Anti-patroon
"Divitis" is wat er gebeurt als elk element in je HTML een <div> is. Hier is een voor/na-vergelijking die het probleem toont:
<!-- Before: divitis -->
<div class="page">
<div class="header">
<div class="brand">TechBlog</div>
<div class="nav">
<div class="nav-item"><a href="/posts">Posts</a></div>
</div>
</div>
<div class="post">
<div class="post-title">Why TypeScript Is Worth It</div>
<div class="post-meta">By Bob — Jan 2026</div>
<div class="post-body">TypeScript adds static types to JavaScript...</div>
</div>
</div>
<!-- After: semantic HTML -->
<body>
<header>
<span class="brand">TechBlog</span>
<nav>
<a href="/posts">Posts</a>
</nav>
</header>
<main>
<article>
<header>
<h1>Why TypeScript Is Worth It</h1>
<p>By Bob — <time datetime="2026-01-10">January 10, 2026</time></p>
</header>
<p>TypeScript adds static types to JavaScript...</p>
</article>
</main>
</body>De semantische versie is daadwerkelijk korter, heeft minder CSS-klassenamen nodig en geeft browsers en hulptools alles wat ze nodig hebben om de paginastructuur te begrijpen. Je kunt alles nog steeds precies hetzelfde stylen met CSS — semantische elementen leggen geen visuele beperkingen op.
ARIA-rollen — Laatste Redmiddel, Niet Eerste Stap
ARIA-rollen laten je semantische betekenis toevoegen aan elementen die het van nature niet hebben. Het probleem is dat ontwikkelaars vaak naar ARIA grijpen wanneer een semantisch HTML-element het werk beter zou doen. De eerste regel van ARIA: gebruik geen ARIA als je native HTML kunt gebruiken.
<!-- Wrong: using ARIA where native HTML works -->
<div role="navigation">
<a href="/home">Home</a>
</div>
<!-- Right: just use the semantic element -->
<nav>
<a href="/home">Home</a>
</nav>
<!-- ARIA is appropriate here: custom widget with no HTML equivalent -->
<div
role="tablist"
aria-label="Code examples"
>
<button role="tab" aria-selected="true" aria-controls="panel-js">JavaScript</button>
<button role="tab" aria-selected="false" aria-controls="panel-py">Python</button>
</div>Gebruik ARIA voor interactieve widgets die native HTML niet dekt — tabbladpanelen, comboboxen, boomstructuurweergaven, datumkiezers. Voor structurele landmarks zoals navigatie, headers en hoofdinhoud, vertrouw altijd op native elementen.
Een Volledige Blogpaginastructuur
Zo ziet een volledig semantische blogpagina eruit. Dit is het patroon dat gebruikt wordt op sites die goed scoren in toegankelijkheidsaudits zonder extra moeite:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Why TypeScript Is Worth It — TechBlog</title>
</head>
<body>
<header>
<a href="/" class="logo">TechBlog</a>
<nav aria-label="Site navigation">
<ul>
<li><a href="/posts">Posts</a></li>
<li><a href="/topics">Topics</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>
</header>
<main>
<article>
<header>
<h1>Why TypeScript Is Worth It</h1>
<address>
By <a rel="author" href="/authors/bob">Bob Martinez</a>
</address>
<p>Published <time datetime="2026-01-10">January 10, 2026</time></p>
</header>
<section>
<h2>The Setup Cost Is Real but Front-Loaded</h2>
<p>TypeScript adds a compilation step and requires type annotations...</p>
<figure>
<pre><code>interface User {
id: number;
name: string;
email: string;
}</code></pre>
<figcaption>Listing 1: A typed User interface catches shape errors at compile time.</figcaption>
</figure>
</section>
<section>
<h2>Where TypeScript Pays Off</h2>
<p>The ROI kicks in as team size and codebase complexity grows...</p>
</section>
<footer>
<p>
Tagged: <a href="/tags/typescript">TypeScript</a>,
<a href="/tags/javascript">JavaScript</a>
</p>
</footer>
</article>
<aside aria-label="Related articles">
<h2>You Might Also Like</h2>
<ul>
<li><a href="/ts-vs-js">TypeScript vs JavaScript — A Practical Comparison</a></li>
<li><a href="/ts-generics">TypeScript Generics Explained</a></li>
</ul>
</aside>
</main>
<footer>
<nav aria-label="Footer navigation">
<a href="/privacy">Privacy</a>
<a href="/terms">Terms</a>
</nav>
<p><small>© 2026 TechBlog</small></p>
</footer>
</body>
</html>Let op het dubbele gebruik van <header> en <footer> — eenmaal op paginaniveau, eenmaal binnen <article>. Dat is opzettelijk en correct. Let ook op twee <nav>-elementen met verschillende aria-label-waarden — dit voorkomt dat schermlezers twee identieke "navigatie"-gebieden opsommen.
Snelle Referentie: Handige Tools
Als je met HTML werkt en je markup wilt opschonen of valideren, zal HTML Formatter je code netjes opmaken, en HTML Validator vangt structurele fouten op zoals niet-gesloten tags en ontbrekende verplichte attributen. Voor een diepgaandere toegankelijkheidsaudit heeft web.dev/accessibility uitstekende diagnostiek en uitleg.
Samenvatting
Semantische HTML gaat niet over het volgen van regels omwille van de regels — het gaat over het schrijven van code die duidelijk communiceert naar browsers, zoekmachines, hulptools en de volgende ontwikkelaar die jouw template leest. De kernelementen zijn eenvoudig: <header>, <nav>, <main>, <article>, <section>, <aside> en <footer> dekken de overgrote meerderheid van echte paginastructuren. Voeg <figure>, <time> en <address> toe waar ze passen, grijp naar ARIA alleen als native HTML tekortschiet, en je hebt markup waar het echt prettig mee werken is.