Se hai usato <div> per tutto — wrapper di pagina, navigazione, contenitore di articolo, sidebar — non sei solo. Era la scelta predefinita per anni. Ma HTML ha avuto elementi semantici propri fin da HTML5, e usarli rende il codice più leggibile, migliore per la SEO e genuinamente più accessibile. Approfondiamo gli elementi che contano davvero.
La parola "semantico" significa semplicemente che l'elemento trasmette un significato oltre alla sua presentazione visiva. Un <div> non significa nulla — è un blocco generico. Un <nav> dice al browser, ai motori di ricerca e alle tecnologie assistive: "questo contiene link di navigazione." Quel contesto non costa nulla da aggiungere e ripaga in molti modi.
Perché la Semantica è Importante
Tre vantaggi concreti, non teorici:
- SEO. I motori di ricerca usano la struttura del documento per capire la gerarchia dei contenuti. Un elemento
<main>segnala il contenuto principale. Un<article>al suo interno segnala un contenuto autonomo. Google usa questi segnali per classificare le pagine. - Accessibilità. I lettori di schermo espongono le regioni landmark agli utenti. Con
<nav>,<main>e<aside>presenti, gli utenti da tastiera possono saltare direttamente alla sezione desiderata — senza fare tab su ogni link della pagina. - Manutenibilità. Un nuovo sviluppatore che legge il tuo template capisce immediatamente la struttura della pagina.
<header>/<main>/<footer>si documenta da solo, a differenza di<div class="top">/<div class="content">/<div class="bottom">.
Gli Elementi di Layout Principali
Questi cinque elementi gestiscono lo scheletro esterno della maggior parte delle pagine. Usali in ogni pagina e hai già vinto metà della battaglia semantica:
<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>. Contenuto introduttivo per la pagina o una sezione. Di solito contiene il logo, il titolo del sito e la navigazione principale. Puoi usarlo anche dentro un<article>per il blocco di intestazione dell'articolo.<nav>. Un insieme di link di navigazione. Non ogni gruppo di link ha bisogno di un<nav>— usalo per i blocchi di navigazione principali come la nav del sito o la paginazione.<main>. Il contenuto dominante della pagina. Deve esserci solo un<main>per pagina e non deve contenere elementi ripetuti tra le pagine (header, nav, footer).<aside>. Contenuto tangenzialmente correlato al contenuto principale. Sidebar, citazioni estratte, articoli correlati. I lettori di schermo lo espongono come landmark complementare.<footer>. Footer per la pagina o una sezione. Può contenere informazioni sul copyright, navigazione secondaria, link di contatto o una breve nota sull'autore.
<header> e <footer> non sono limitati al livello di pagina. Ogni <article> o <section> può avere il proprio <header> e <footer>. Questo è particolarmente utile per le righe con i dati dell'autore nei post del blog e per i metadati a livello di articolo.article vs section — Quando Usare Ciascuno
Questo è il punto che crea più confusione. La regola empirica che funziona davvero: se il contenuto avrebbe senso se pubblicato autonomamente (ad es. come voce RSS o condiviso su un altro sito), è un <article>. Se ha senso solo come parte di un insieme più grande, è una <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> dovrebbe avere sempre un'intestazione (da <h2> a <h6>). Se la tua sezione non ha un'intestazione, di solito è un segnale che dovresti usare un <div>. Lo spec WHATWG è chiaro: <section> è per raggruppamenti tematici, non per divisioni di layout arbitrarie.
figure, figcaption, time e address
Quattro elementi che gli sviluppatori spesso dimenticano ma usano regolarmente:
<!-- 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>. Qualsiasi contenuto autonomo referenziato dal flusso principale — immagini, listati di codice, grafici, video. Il punto chiave: potrebbe essere spostato in appendice senza interrompere il flusso di lettura.<figcaption>. La didascalia per un<figure>. Deve essere il primo o l'ultimo figlio di<figure>. Fornisce un'associazione semantica tra didascalia e contenuto che un<p>sotto un'immagine non offre.<time>. Date leggibili dagli esseri umani con un attributodatetimeleggibile dai computer. Il valore didatetimeusa il formato ISO 8601. I motori di ricerca lo usano per i markup di eventi e i segnali di freschezza.<address>. Informazioni di contatto per l'antenato<article>più vicino (o l'intero<body>). Non è un elemento indirizzo generico — è specifico per le informazioni di contatto dell'autore del contenuto o del proprietario del sito.
L'Anti-Pattern della Divite
La "divite" è ciò che accade quando ogni elemento nel tuo HTML è un <div>. Ecco un confronto prima/dopo che mostra il problema:
<!-- 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>La versione semantica è in realtà più breve, richiede meno nomi di classi CSS e fornisce a browser e strumenti assistivi tutto il necessario per capire la struttura della pagina. Puoi comunque stilizzare tutto esattamente nello stesso modo con CSS — gli elementi semantici non impongono alcun vincolo visivo.
Ruoli ARIA — Ultima Risorsa, Non Prima Mossa
I ruoli ARIA ti permettono di aggiungere significato semantico a elementi che non ce l'hanno nativamente. Il problema è che gli sviluppatori spesso ricorrono ad ARIA quando un elemento HTML semantico farebbe il lavoro meglio. La prima regola di ARIA: non usare ARIA se puoi usare HTML nativo.
<!-- 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>Usa ARIA per widget interattivi che l'HTML nativo non copre — pannelli a schede, combobox, visualizzazioni ad albero, selettori di date. Per landmark strutturali come navigazione, intestazioni e contenuto principale, affidati sempre agli elementi nativi.
Struttura Completa di una Pagina Blog
Ecco come appare una pagina blog completamente semantica. Questo è il pattern usato sui siti che ottengono buoni risultati nei controlli di accessibilità senza sforzo aggiuntivo:
<!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>Nota il doppio uso di <header> e <footer> — una volta al livello di pagina, una volta dentro <article>. È intenzionale e corretto. Nota anche due elementi <nav> con valori aria-label distinti — questo evita che i lettori di schermo elenchino due identiche regioni di "navigazione".
Riferimento Rapido: Strumenti Utili
Se stai lavorando con HTML e vuoi ripulire o validare il tuo markup, HTML Formatter abbellirà e sistemerà il tuo codice, e HTML Validator individua errori strutturali come tag non chiusi e attributi richiesti mancanti. Per un'analisi di accessibilità più approfondita, web.dev/accessibility offre ottimi strumenti diagnostici e spiegazioni.
Conclusione
L'HTML semantico non riguarda il seguire regole per il gusto di farlo — si tratta di scrivere codice che comunica chiaramente a browser, motori di ricerca, strumenti assistivi e al prossimo sviluppatore che leggerà il tuo template. Gli elementi principali sono semplici: <header>, <nav>, <main>, <article>, <section>, <aside> e <footer> coprono la stragrande maggioranza delle strutture di pagina reali. Aggiungi <figure>, <time> e <address> dove si adattano, ricorri ad ARIA solo quando l'HTML nativo non è sufficiente, e avrai un markup che è davvero un piacere lavorarci.