Struttura HTML per chi inizia
Nota iniziale
Ogni singola pagina web che visiti, da Wikipedia a un'applicazione complessa, si appoggia su uno scheletro invisibile: il codice HTML. Prima ancora di pensare ai colori, alle animazioni o alle funzionalità dinamiche, è questa struttura portante a disporre le informazioni in modo logico.
Proprio per questo, anziché imparare a memoria decine di tag, ci concentreremo su come è strutturata una pagina. Scrivere codice pulito e ordinato non serve per fare bella figura, ma per rendere il sito accessibile a chiunque e facile da trovare sui motori di ricerca. Qui vediamo i concetti base per partire, ma il bello viene con la pratica: prova a sperimentare e a scrivere il tuo codice fin da subito, un passo alla volta.

1. Come ragiona HTML (e cosa non è)
Partiamo da un punto fondamentale: HTML non è un linguaggio di programmazione. Non compie calcoli, non prende decisioni logiche e non sa fare operazioni matematiche. HTML sta per HyperText Markup Language (Linguaggio di Marcatura Ipertestuale).
Il suo unico scopo è "marcare" il testo puro per dire al browser: "Questo pezzo è un titolo, questa frase è un paragrafo e questo elemento è un pulsante".
Quando scrivi un file HTML e lo apri, il browser lo legge e crea una struttura ad albero chiamata DOM (Document Object Model). Immaginalo come una ramificazione di scatole: la scatola principale contiene scatole più piccole, che a loro volta contengono testi o altre scatole. CSS e JavaScript agiranno in seguito proprio su questo albero. Senza un HTML solido, non avrebbero nulla da stilizzare o animare.
Ora che abbiamo un'idea di come il browser organizza le informazioni in scatole (il DOM), iniziamo a creare la nostra prima scatola. Per farlo, partiamo dall'elemento base dell'HTML: il tag.
2. Anatomia di un Tag e la Regola del Nesting
Per dare una struttura a una pagina web, HTML usa i tag (che in inglese significa letteralmente "etichette"). Immagina di avere del testo semplice e di voler dire al browser: "Questo pezzo di testo è un paragrafo, mentre quest'altro è un titolo". Per farlo, "incolli" un'etichetta prima e dopo il testo.
Queste etichette si scrivono racchiuse tra parentesi angolari (i simboli di minore < e maggiore >) e, nella maggior parte dei casi, lavorano sempre in coppia:
- Il tag di apertura (l'inizio): indica l'inizio del nostro elemento. Si scrive inserendo il nome dell'etichetta tra le parentesi angolari. Ad esempio, per iniziare un paragrafo usiamo il tag
<p>(la "p" sta per paragraph). - Il contenuto: è tutto ciò che si trova racchiuso tra l'etichetta iniziale e quella finale (ad esempio, il testo del paragrafo).
- Il tag di chiusura (la fine): indica al browser dove finisce l'elemento. È identico a quello di apertura, ma contiene una barra obliqua
/(chiamata slash) posizionata subito dopo la prima parentesi angolare, in questo modo:</p>. Pensa alla barra come a un cartello di "stop".
L'unione di queste tre parti (tag di apertura + contenuto + tag di chiusura) forma quello che in gergo si chiama elemento HTML.
indica l'inizio del nostro elemento. Per iniziare un paragrafo usiamo il tag <p>.
è tutto ciò che si trova racchiuso tra l'etichetta iniziale e quella finale.
indica al browser dove finisce l'elemento. Contiene la barra slash (/) prima del nome, come nell'esempio: </p>.
I tag possono contenere anche degli attributi, ovvero delle informazioni extra inserite esclusivamente all'interno del tag di apertura. Gli attributi servono a specificare caratteristiche o comportamenti dell'elemento (come la destinazione di un link o la sorgente di un'immagine) e si scrivono sempre nella forma nome-attributo="valore" (detta anche coppia chiave="valore").
Vediamo l'esempio di un link (il tag <a>):
l'indirizzo o parametro a cui puntare (in questo esempio, href).
il valore specifico associato all'attributo, scritto sempre tra virgolette ("https://codedge.it").
In questo esempio:
- La chiave (o nome dell'attributo) è
href, che indica al browser: "Voglio impostare un indirizzo web di destinazione". - Il valore è
"https://codedge.it"(scritto sempre tra virgolette dopo il segno di uguale=), che definisce l'indirizzo web specifico.
Alcuni tag rari non contengono testo e non racchiudono nulla, quindi non hanno bisogno di un tag di chiusura. Vengono chiamati tag vuoti (o auto-chiudenti). Un esempio è il tag <img> per mostrare un'immagine o <br> per andare a capo.
La regola del Nesting (Annidamento)
In HTML, quando inseriamo un tag all'interno di un altro, parliamo di Nesting (annidamento). Immagina questa struttura come una serie di scatole cinesi o matrioske: una scatola più piccola deve essere inserita interamente dentro una scatola più grande.
C'è una regola d'oro semplicissima da ricordare per non sbagliare mai:
L'ultimo tag che apri deve essere sempre il primo che chiudi. Non puoi mai incrociare i tag!
Per capire questo concetto in modo semplicissimo, pensa alle parentesi che usi quando scrivi a mano. Se apri una parentesi tonda ( e poi una parentesi quadra [, devi obbligatoriamente chiudere prima la quadra e poi la tonda. Non puoi incrociarle in questo modo: ( [ ) ].
Vediamo il confronto diretto tra la struttura errata e quella corretta.
❌ L'errore più comune (Tag incrociati)
Immagina di voler mettere una parola in grassetto (usando il tag <strong>) all'interno di un paragrafo (usando <p>):
<p>Questo testo è <strong>molto importante.</p></strong>Se proviamo a visualizzarlo come scatole, notiamo subito l'errore:
In questo caso, le scatole si tagliano a metà l'una con l'altra. Questo costringe il browser a fare supposizioni e può rompere l'aspetto grafico della pagina.
✅ La struttura corretta (Scatole ordinate)
Per correggere l'errore, dobbiamo assicurarci che la scatola più piccola (il grassetto) si chiuda prima della scatola più grande (il paragrafo):
<p>Questo testo è <strong>molto importante.</strong></p>Vediamo come le scatole si inseriscono perfettamente l'una dentro l'altra:
In questo modo, la gerarchia è pulita, logica e facilissima da interpretare per qualsiasi browser o lettore di schermo.
Sebbene i browser moderni facciano del loro meglio per "correggere" da soli gli errori di nesting, farlo li costringe a rallentare e a indovinare le tue intenzioni. Questo porta spesso a bug grafici inaspettati, problemi sui dispositivi mobili o difficoltà per le persone che usano lettori di schermo per non vedenti.
Ora che sai come scrivere un singolo tag, come impostare gli attributi e come incastrare le scatole l'una dentro l'altra senza fare errori, proviamo a unire tutti questi pezzi. Nel prossimo capitolo vedremo lo scheletro di partenza comune a qualsiasi pagina internet esistente.
3. Il boilerplate: i tag di partenza
Nei capitoli precedenti abbiamo visto come il browser costruisce l'albero e come i tag si annidano senza incrociarsi. Ora apriamo un file vero.
Lo scheletro di una pagina è l'intero documento HTML: ogni tag che il browser trasformerà nel DOM. Il boilerplate è più stretto. È solo il kit di partenza: i pochi tag principali già annidati al posto giusto. In VS Code lo ottieni digitando ! e premendo Invio.
Il file inizia con una dichiarazione (DOCTYPE), poi il tag radice <html>. Dentro ci stanno due scatole: <head>, invisibile in pagina, con i meta e il title; e <body>, quello che si vede. Il widget sotto le smonta una alla volta.
Esempio interattivo
Il boilerplate, pezzo per pezzo
Clicca le quattro parti. Guarda l'annidamento: html contiene head e body; head contiene i tag meta e title.
Deve essere la prima riga, prima di <html>. Dice al browser di leggere il file come HTML5 moderno. Se manca, il browser può scivolare in quirks mode.
<html> è il tag radice.Tutto il documento sta dentro questa scatola: prima <head>, poi <body>. È il tag più esterno del boilerplate, non lo scheletro da solo.
<head> stanno i tag meta e il title.I <meta> parlano al browser: charset="UTF-8" perché lettere ed emoji si leggano bene, viewport perché i telefoni scalino la pagina. <title> è il testo della scheda — anche dei preferiti e, di default, dei risultati di ricerca. Niente di tutto questo viene disegnato nel corpo della pagina.
<body> è il fratello di <head>.Tutti e due stanno dentro <html>, mai uno dentro l'altro. Titoli, paragrafi, immagini, form: se il visitatore deve vederlo, sta qui.
lang="it"non è un tag: è un attributo di<html>, una coppianome="valore"solo nel tag di apertura. Dice al browser, ai motori di ricerca e agli screen reader che la pagina è in italiano. Gli attributi non si chiudono.<meta>è un tag, e un tag vuoto: non ha contenuto né chiusura. Cosa fa dipende dai suoi attributi.charset="UTF-8"dice al browser come leggere i caratteri del file, così lettere accentate ed emoji non escono illeggibili.- Il secondo
<meta>usa due attributi:name="viewport"dà il nome all'impostazione,content="…"ne dà il valore. Insieme dicono ai telefoni di non fingere che la pagina sia uno schermo da desktop rimpicciolito.width=device-widthsegue lo schermo vero;initial-scale=1.0parte allo zoom 100%.
Lasciali tutti e tre così. Torneremo sugli attributi più avanti; questi tre stanno già facendo il loro lavoro.
La regola da portarsi dietro è quella del capitolo 2: l'ultimo tag aperto è il primo che chiudi. <head> e <body> stanno interamente dentro <html>; i tag meta e il title stanno interamente dentro <head>.
Ora entriamo nel <body> e iniziamo a riempirlo. Il primo mattone è il testo.
4. Il testo della pagina: paragrafi e titoli
Che cos'è il tag <body>?
Il tag <body> (che in inglese significa "corpo") rappresenta a tutti gli effetti la tela visibile del tuo sito web. Tutto ciò che un utente vede, legge, clicca o con cui interagisce all'interno della finestra del browser — testi, titoli, immagini, video, pulsanti, menu di navigazione, form per i contatti — deve essere posizionato tassativamente all'interno di questa scatola.
Nel capitolo precedente abbiamo visto che una pagina HTML è divisa in due aree principali: l'<head>, che contiene informazioni per il browser, e il <body>, che contiene ciò che appare nella pagina. Per distinguerle meglio, pensa alla struttura di una lettera cartacea:
- Il
<body>è il foglio di carta interno: contiene il messaggio vero e proprio, le parole scritte, i disegni o gli allegati. È la parte che il lettore vede e consulta. - L'
<head>, invece, è paragonabile alla busta: contiene informazioni necessarie per identificare e gestire la lettera, ma non il messaggio destinato al lettore.
Ci sono tre regole d'oro da tenere sempre a mente quando si lavora con il <body>:
- Unicità: Può esistere un solo ed unico tag
<body>all'interno di ogni file HTML. Non puoi avere "due body". - Posizione: Viene aperto subito dopo la chiusura dell'
<head>(cioè dopo</head>) e viene chiuso subito prima del tag finale di chiusura della pagina (cioè prima di</html>). - Niente fuori dai bordi: Scrivere del codice o inserire tag visibili all'esterno di
<body>(ad esempio sotto la sua chiusura) è un grave errore di sintassi. Anche se i browser moderni cercano di rimediare a questo errore "spostando" forzatamente il codice nel body dietro le quinte, questo crea bug molto difficili da individuare nel layout grafico (CSS) e nel comportamento interattivo (JavaScript).
Ora che abbiamo chiaro cos'è questo spazio e perché esiste, iniziamo a riempirlo. Il caso più comune è il testo.
Se scrivi le frasi nude nel <body> e vai a capo nell'editor, il browser le unisce in una riga sola: gli a capo del file non contano. Per fare un blocco serve il tag <p>.
Per spezzare un testo lungo servono i titoli, da <h1> a <h6>. Il numero non è la grandezza del carattere: è il livello nell'indice della pagina. Il widget sotto mostra le stesse parole in quattro strutture.
Esempio interattivo
Le stesse parole, quattro strutture
Clicca ogni vista. A sinistra c'è il codice; a destra ciò che il browser mostra davvero — e, per i titoli, l'indice che costruisce.
<body> Corso di cucina Questa è la prima frase. Questa dovrebbe essere una frase separata. </body>
<body> <p>Questa è la prima frase.</p> <p>Questa è una frase separata.</p> </body>
<h1>Corso di cucina</h1> <h2>Gli attrezzi</h2> <h3>I coltelli</h3> <h3>Le pentole</h3> <h2>Le prime ricette</h2>
<!-- «h2 è troppo grosso, uso h4» --> <h1>Corso di cucina</h1> <h4>Gli attrezzi</h4>
Corso di cucina Questa è la prima frase. Questa dovrebbe essere una frase separata.
Questa è la prima frase.
Questa è una frase separata.
Corso di cucina
Gli attrezzi
I coltelli
Le pentole
Le prime ricette
Corso di cucina
Gli attrezzi
Nel codice vai a capo tre volte, eppure in pagina resta una riga sola. Il browser ignora quegli a capo: per lui è un unico pezzo di testo. Per spezzare la riga sullo schermo serve un tag, non il tasto Invio.
Stesse parole di prima, ma ognuna sta in un <p>. Il browser le mette una sotto l'altra, con un po' di aria in mezzo. È il tag che decide i blocchi: puoi andare a capo dieci volte nel codice, e resta comunque un paragrafo solo.
<h1> è il titolo del libro. <h2> è un capitolo. <h3> è un paragrafo di quel capitolo. A destra vedi l'indice che ne esce: niente buchi, ogni titolo al suo posto. Il fatto che h1 si veda più grosso è solo il default del browser.
Il browser lo disegna più piccolo, e viene la tentazione di usarlo al posto di h2. Ma 4 vuol dire «quarto gradino», non «carattere piccolo». Qui si salta da h1 a h4: nell'indice manca il capitolo e il sotto-capitolo, come un libro che dal 1 passa al 4. Se h2 ti sembra troppo grosso, tieni h2: la grandezza la cambi dopo, con il CSS.
Il paragrafo: <p>
Un <p> racchiude un pensiero compiuto. Hai già visto che è il tag, non Invio, a creare il blocco. Una regola in più, perché il browser non ti avvisa:
Se scrivi <p>Testo <p>altro testo</p></p>, il browser non ti segnala un errore: chiude in autonomia il primo paragrafo appena ne incontra un secondo, e ti ritrovi una struttura diversa da quella che avevi in mente. Un <p> non può contenere altri paragrafi né elementi strutturali come titoli o <div>. Il perché lo vedremo nel capitolo 5.
I titoli: da <h1> a <h6>
Ci sono sei tag di intestazione. Il widget ha mostrato l'idea: il numero è la profondità nell'indice, come i numeri del sommario di un libro. Quell'indice è ciò che Google e gli screen reader usano per saltare da una sezione all'altra.
Le tre regole dei titoli
- Un solo
<h1>per pagina. È il titolo del documento, quindi ce n'è uno solo, come il titolo di un libro. - Non saltare i livelli. Dopo un
<h2>puoi mettere un<h3>, non direttamente un<h4>: nell'indice apparirebbe un buco. - Scegli il livello in base alla logica, mai in base a quanto è grande a schermo. Il browser dà ai titoli una dimensione predefinita solo per comodità: quella dimensione la cambierai con il CSS, senza toccare il tag.
«Questo <h2> viene troppo grosso, uso un <h4>.» h4 non è una versione piccola di h2: è un titolo di quarto livello. Nell'indice spariscono due gradini. Tieni il livello giusto e cambia la grandezza con il CSS.
Con titoli e paragrafi si stabilisce l'ossatura generale di una pagina. Avrai però notato che questi elementi iniziano su una nuova riga, mentre altri tag possono marcare singole parole senza interrompere il testo. Nel prossimo capitolo mettiamo a confronto questi due comportamenti — a blocco e in linea — prima di scoprire i tag che lavorano dentro le frasi.
5. Elementi a blocco e in linea: come si dispongono i tag
Prima di imparare altri tag serve una mappa di come il browser li dispone nella pagina.
Un elemento a blocco (block) inizia su una nuova riga e prende tutta la larghezza disponibile. Per questo due paragrafi o due titoli finiscono uno sotto l'altro, anche quando il testo è corto.
Un elemento in linea (inline) non apre una nuova riga: occupa solo lo spazio delle sue lettere e resta nel flusso della frase. Serve a marcare una parola senza spezzare il paragrafo. Esempi: <strong>, <em>, <code>, <a>.
L'in linea vive dentro un blocco, non il contrario. E <br> non serve a fare spazio tra due scatole: serve quando l'a capo è parte del testo, come in un indirizzo. Il widget sotto mostra questi quattro punti.
Esempio interattivo
A blocco o in linea
Clicca ogni vista. Le scatole tratteggiate sono tutta la riga. Le parole evidenziate restano nella frase.
<p>Corto.</p> <p>Corto anche questo.</p>
<p> Il tag <strong>title</strong> è <code>obbligatorio</code>. </p>
<p>Primo blocco.</p> <p> Qui dentro <strong>resto in linea</strong>. </p>
<!-- sbagliato: fare spazio --> <p>Sopra</p> <br><br><br> <p>Sotto</p> <!-- giusto: l'a capo è il contenuto --> <p> Codedge S.r.l.<br> Via Roma 12 </p>
Il tag title è obbligatorio.
· · · tre <br>
Codedge S.r.l.
Via Roma 12
Il testo è corto, eppure ogni <p> inizia sotto il precedente. Il browser gli dà tutta la larghezza, come due scatole una sopra l'altra. I titoli fanno lo stesso.
<strong> e <code> non vanno a capo. Marcano una parola e il resto della frase continua accanto. Occupano solo lo spazio delle lettere.
I paragrafi sono le scatole. Dentro una scatola, le parole marcate restano in fila. Non il contrario: un <p> non può stare dentro uno <strong>.
<br> non serve a fare spazio.Tre <br> di fila per allontanare due pezzi è l'errore da principiante. <br> si usa quando l'a capo è parte del testo: un indirizzo, un verso. Lo spazio tra le scatole lo fa il CSS.
Gli elementi a blocco che userai davvero
| Tag | Significato | Resa predefinita |
|---|---|---|
| <p> | Un paragrafo di testo. | Nuova riga, con spazio sopra e sotto |
| <h1>…<h6> | I titoli, ordinati per livello gerarchico. | Nuova riga, testo in evidenza |
| <div> | Un contenitore neutro senza significato semantico. | Nuova riga, tutta la larghezza disponibile |
| <ul> <ol> <li> | Liste non ordinate, liste ordinate e loro elementi. | Elenco verticale con punti o numeri |
| <blockquote> | Una citazione estesa proveniente da un'altra fonte. | Blocco separato, generalmente rientrato |
| <pre> | Testo preformattato che conserva spazi e ritorni a capo. | Blocco con carattere monospazio |
| <figure> | Un contenuto autonomo, come un'immagine con didascalia. | Blocco separato con margini |
| <header> <nav> <main> <section> <article> <aside> <footer> | Le regioni semantiche che organizzano la pagina. | Nuova riga, tutta la larghezza disponibile |
| <form> | Un insieme di campi per raccogliere dati dall'utente. | Blocco separato |
| <hr> | Uno stacco tematico tra due parti del contenuto. | Linea orizzontale su una nuova riga |
Elementi in linea
Oltre a quelli già visti, restano in linea anche <span>, <abbr> e <img>.
“A blocco” e “in linea” descrivono qui il modo in cui il browser dispone normalmente gli elementi. Con la proprietà CSS display potrai cambiarne la resa grafica, ma non il loro significato né le regole su quali contenuti possono racchiudere.
Marcare le parole con i tag in linea
Ora concentriamoci sugli elementi in linea che servono a dare un significato preciso a una o più parole senza interrompere il flusso del paragrafo.
Prima di scoprire i singoli tag, c'è una regola d'oro da comprendere: l'HTML serve a definire il significato (la semantica) del testo, non il suo aspetto estetico. Oggi, qualsiasi effetto puramente visivo (come cambiare colore, ingrandire un carattere o applicare stili complessi) si gestisce in modo molto più efficace e professionale con il CSS.
Usa i tag descritti in questo capitolo solo quando vuoi dare un significato preciso a una parola (ad esempio per far capire a Google o a uno screen reader che un termine è cruciale o che si tratta di un'abbreviazione). Se il tuo scopo è unicamente decorativo o grafico, dovrai invece affidarti al CSS.
<p>Ricorda: il tag <code><title></code> è <strong>obbligatorio</strong> in ogni pagina.</p>La frase resta una frase sola: <strong> e <code> non creano un nuovo blocco, marcano una porzione di testo esistente.
I tag in linea che userai davvero
| Tag | Significato | Resa predefinita |
|---|---|---|
| <strong> | Contenuto di forte importanza, un avvertimento, una parola critica. | Grassetto |
| <em> | Enfasi: la parola su cui cade l'accento leggendo la frase ad alta voce. | Corsivo |
| <code> | Un frammento di codice o un nome tecnico (un file, un comando, un tag). | Carattere monospazio |
| <mark> | Testo evidenziato perché rilevante in questo contesto (es. il termine cercato). | Sfondo giallo |
| <a> | Un collegamento. È il tag in linea più importante: ha il capitolo 7 tutto per sé. | Testo blu sottolineato |
| <abbr> | Un'abbreviazione; il significato esteso va nell'attributo title. | Nessuna, o sottolineatura punteggiata |
| <time> | Una data o un orario, in formato leggibile dalle macchine con datetime. | Nessuna |
| <small> | Note a margine: copyright, clausole, precisazioni legali. | Carattere più piccolo |
| <del> <ins> | Testo rimosso e testo aggiunto rispetto a una versione precedente. | Barrato / sottolineato |
| <sub> <sup> | Pedice e apice: formule chimiche, potenze, note. | Testo abbassato / alzato |
| <span> | Nessun significato: contenitore neutro, ne parliamo nel capitolo 11. | Nessuna |
<p>
L'<abbr title="HyperText Markup Language">HTML</abbr> nasce nel
<time datetime="1991">1991</time>. La formula dell'acqua è
H<sub>2</sub>O e il prezzo è <del>20 €</del> <ins>15 €</ins>.
</p><strong> o <b>? <em> o <i>?
Esistono anche <b> e <i>, che a schermo danno lo stesso identico risultato (grassetto e corsivo). Non sono tag eliminati dallo standard, ma hanno un significato diverso: indicano un testo graficamente distinto senza attribuirgli importanza (per esempio un nome scientifico in corsivo, o le parole chiave di un articolo in neretto).
Se la parola è importante o va enfatizzata nella lettura, usa <strong> ed <em>: uno screen reader può cambiare tono di voce, un motore di ricerca ne tiene conto. Se invece vuoi solo un effetto grafico, non usare né gli uni né gli altri: quello è lavoro del CSS.
Andare a capo per davvero: <br> e <hr>
Abbiamo detto che premere Invio nel codice non manda a capo. Quando l'andata a capo fa parte del contenuto — un indirizzo postale, i versi di una poesia — si usa il tag vuoto <br>:
<p>
Codedge S.r.l.<br>
Via Roma 12<br>
00100 Roma
</p><br> per creare spazioMettere tre <br> di fila per distanziare due blocchi è l'errore da principiante più riconoscibile che esista. Lo spazio tra gli elementi si regola con la proprietà CSS margin. <br> serve solo quando la riga nuova è parte del testo.
Il tag <hr>, anch'esso vuoto, segna invece uno stacco tematico tra due parti di contenuto (il browser lo disegna come una linea orizzontale). Anche qui: se ti serve solo una linea decorativa, usa il CSS.
Scrivere caratteri speciali: le entità
Cosa succede se vuoi mostrare a schermo proprio il simbolo <? Il browser penserebbe che stai aprendo un tag. Per questo esistono le entità HTML: sequenze che iniziano con & e finiscono con ;.
| Scrivi | Ottieni | Quando serve |
|---|---|---|
| < | < | Mostrare del codice HTML dentro una pagina |
| > | > | Come sopra |
| & | & | La e commerciale, che altrimenti apre un'entità |
| | spazio unificatore | Tenere due parole sulla stessa riga (es. 10 kg) |
| © | © | Simbolo di copyright nel footer |
Per lettere accentate ed emoji non servono entità: basta che il file dichiari <meta charset="UTF-8">, come nel boilerplate del capitolo 3.
I commenti
Puoi lasciare note nel codice che il browser ignora completamente, racchiudendole tra <!-- e -->:
<!-- Sezione offerte: da aggiornare ogni lunedì -->
<p>Sconto del 20% su tutto il catalogo.</p>Non appaiono nella pagina, ma restano nel file: chiunque può leggerli con "Visualizza sorgente pagina". Non scriverci password, note riservate o commenti sui clienti.
Blocco e in linea non decidono da soli l'annidamento
La disposizione sullo schermo non basta a stabilire quali tag possano stare dentro altri tag. Ogni elemento HTML ammette determinati tipi di contenuto: per esempio, un <p> può contenere testo ed elementi che marcano le parole, ma non strutture come titoli, altri paragrafi o <div>.
Non inserire elementi strutturali come <h2>, <p> o <div> dentro <p>, <span>, <strong>, <em> e gli altri tag usati per marcare porzioni di testo. Codice come <p><div>...</div></p> non è valido: il browser prova a correggerlo e può produrre una struttura diversa da quella che avevi scritto.
Il tag <a> è un caso particolare: può racchiudere sia una porzione di testo sia, quando il contesto lo consente, un intero blocco di contenuto. Questo permette di rendere cliccabile un'intera scheda anziché soltanto le sue parole:
<a href="/prodotti/tazza/">
<h3>Tazza Codedge</h3>
<p>Ceramica smaltata, 350 ml.</p>
</a>Ora sai riconoscere i due comportamenti più comuni, usare i tag che marcano il testo e non confondere la resa grafica con la struttura del documento. Manca un pezzo trasversale: gli attributi che puoi mettere sui tag e che useremo di continuo nei prossimi capitoli.
6. Gli attributi universali: dare un'identità ai tag
Fino ad ora abbiamo visto attributi che funzionano solo su alcuni tag: href, per esempio, ha senso su un link ma non su un paragrafo. L'HTML mette anche degli attributi globali: li puoi scrivere su qualsiasi elemento.
I due che contano di più sono id e class. Entrambi sono etichette, così puoi ritrovare un elemento più avanti. Cambia solo quante volte l'etichetta può comparire:
idè un nome unico, come un numero di matricola. In una pagina può esistere una sola volta.classè un nome di gruppo. La stessa classe può stare su quanti elementi vuoi, e un elemento può avere più classi separate da uno spazio.
Da soli non cambiano colore, misura o posizione. Preparano il terreno per un link, un foglio di stile o del JavaScript. Nell'HTML si scrive solo il nome: niente # e niente .. Il widget sotto mostra questi quattro punti.
Esempio interattivo
id e class
Un nome per un elemento. Un nome per un gruppo. Nessuno dei due dipinge la pagina.
<p id="contatti">Dove trovarci</p> <p class="avviso">Spedizioni regolari.</p> <p>Nessuna etichetta.</p>
<h2 id="contatti">Dove trovarci</h2> <p>Via Roma 12.</p>
<p class="avviso">Spedizioni regolari.</p> <p class="avviso urgente">Ultimo giorno per ordinare.</p> <p>Fuori dal gruppo.</p>
<!-- sbagliato --> <h2 id="#contatti"> <p class=".avviso"> <!-- giusto --> <h2 id="contatti"> <p class="avviso">
Un id o una class non cambiano colore, misura o posizione. Sono nomi, pronti per quando un link, un foglio di stile o del JavaScript li andranno a cercare.
id è un nome unico.Come un numero di matricola: appartiene a un solo elemento. In questa pagina può esistere un solo contatti. Serve quando ti serve quel punto preciso: una sezione a cui saltare, un campo da etichettare.
class è un nome di gruppo.La stessa classe può stare su quanti elementi vuoi. Uno spazio separa due classi: avviso urgente non è un nome con lo spazio dentro, sono due gruppi. Nel dubbio, usa class.
Il CSS più avanti li cercherà come #contatti e .avviso. Quei simboli sono la ricerca, non il nome. Li metti nel tag e il nome diventa sbagliato. L'unica eccezione è un link verso un id: href="#contatti".
1. L'attributo id: un nome unico
L'id assegna un nome che identifica un singolo elemento della pagina. Si scrive come qualunque altro attributo, dentro il tag di apertura:
<h2 id="contatti">Dove trovarci</h2>
<p>Siamo in via Roma 12, aperti dal lunedì al venerdì.</p>A cosa serve avere un nome unico?
- Nell'HTML: per creare link che portano a un punto preciso della pagina (le ancore, che vedremo nel prossimo capitolo) e per collegare l'etichetta di un modulo al suo campo di inserimento.
- Nel CSS: per applicare uno stile a quell'unico elemento.
- In JavaScript: per raggiungere quell'elemento specifico e modificarlo, per esempio in risposta a un clic.
id:- Deve essere unico nella pagina: se lo ripeti, la pagina si vede lo stesso, ma link e JavaScript troveranno solo il primo elemento e il comportamento diventa imprevedibile.
- Non può essere vuoto e non può contenere spazi: scrivi
sezione-contatti, nonsezione contatti. - Distingue maiuscole e minuscole:
Contattiecontattisono due id diversi. - Per stare tranquillo, usa solo lettere minuscole, numeri e trattini, e comincia sempre con una lettera.
2. L'attributo class: un'etichetta di gruppo
La class raggruppa elementi sotto una categoria comune. La stessa classe può comparire su quanti elementi vuoi:
<p class="avviso">Le spedizioni sono regolari.</p>
<p class="avviso">Ultimo giorno utile per ordinare!</p>
<p>Questo paragrafo non ha classi: non fa parte del gruppo.</p>Un elemento può anche appartenere a più gruppi contemporaneamente: basta scrivere i nomi separati da uno spazio. Non è "una classe con lo spazio dentro", sono due classi distinte:
<p class="avviso urgente">Consegne sospese oggi.</p>A cosa serve raggruppare?
- Nel CSS: per dare lo stesso aspetto a tutti gli elementi del gruppo scrivendo la regola una volta sola.
- In JavaScript: per agire su tutti gli elementi del gruppo con una sola istruzione.
- Per chi legge il codice: un nome come
scheda-prodottoracconta a colpo d'occhio che ruolo ha quell'elemento.
# e . non si scrivono nell'HTML!Quando più avanti incontrerai il CSS, vedrai gli id preceduti dal cancelletto (#contatti) e le classi precedute dal punto (.avviso). Quei simboli servono solo a richiamarli da fuori: dicono al browser "cerca l'elemento che ha questo id" o "cerca gli elementi che hanno questa classe". Nel tag HTML, invece, scrivi soltanto il nome.
- ❌ Errato:
<h2 id="#contatti">—<p class=".avviso"> - ✅ Corretto:
<h2 id="contatti">—<p class="avviso">
L'unica eccezione che vedrai in HTML è il href di un link interno, che punta a un id e quindi usa il cancelletto: <a href="#contatti">.
Se ti serve raggiungere quel preciso elemento (una sezione a cui puntare con un link, un campo di un modulo), usa id. Se stai descrivendo un tipo di elemento che potrebbe ripetersi (un pulsante, un box evidenziato, una scheda prodotto), usa class. Nel dubbio, usa class: non rischi mai di creare doppioni.
Altri attributi globali utili
Oltre a questi due, ce ne sono altri che ti capiterà di incontrare spesso:
| Attributo | A cosa serve? | Nota pratica |
|---|---|---|
| lang | Dichiara la lingua del testo, utile ai motori di ricerca e ai lettori vocali. | Si mette sul tag <html> per l'intera pagina (es. lang="it") e su un singolo elemento solo quando cambia lingua. |
| title | Mostra un piccolo fumetto di spiegazione (tooltip) al passaggio del mouse. | Non metterci informazioni indispensabili: su smartphone e per chi naviga da tastiera spesso non compare affatto. |
| hidden | Dice al browser che l'elemento non è ancora pertinente: non viene mostrato né letto dai lettori vocali. | Non vuole un valore, basta scriverlo nel tag: <p hidden>...</p>. |
| style | Applica regole CSS direttamente a quel singolo tag. | Meglio evitarlo: mescola grafica e struttura e non è riutilizzabile. Usa class e un foglio di stile. |
Ad esempio, se in una pagina scritta in italiano inserisci una frase o una citazione in inglese, è un'ottima pratica segnalarlo così:
<p>Il motto dell'azienda è <span lang="en">think different</span>.</p>In questo modo i lettori vocali usati da chi ha difficoltà visive pronunceranno la frase all'inglese, anziché leggerla all'italiana.
Ora che sai dare un id a un elemento, possiamo affrontare il tag che ha reso il web una rete: il link.
7. I link: collegare le pagine
Il collegamento ipertestuale è ciò che trasforma pagine isolate in un sito, e i siti in un web. Si crea con il tag <a> (anchor, ancora) e il suo attributo href (hypertext reference), che indica la destinazione.
<a href="https://codedge.it">Vai al sito di Codedge</a>Il testo tra i due tag è la parte cliccabile e visibile; href è l'indirizzo, che l'utente non vede. Un <a> senza href non è un link: è solo testo.
Le destinazioni possibili
| Tipo | Esempio di href | Effetto |
|---|---|---|
| URL assoluto | https://google.com | Va su un altro sito. Serve l'indirizzo completo con https://. |
| Percorso dalla radice | /contatti/ | Va a una pagina del tuo sito partendo dalla sua radice. |
| Percorso relativo | prodotti.html | Va a un file cercandolo a partire dalla cartella della pagina attuale. |
| Ancora | #contatti | Scorre fino all'elemento con id="contatti" nella pagina corrente. |
| mailto:[email protected] | Apre il programma di posta con il destinatario già compilato. | |
| Telefono | tel:+390612345 | Su smartphone avvia la chiamata. |
I percorsi relativi, spiegati una volta per tutte
È il punto in cui si inciampa spesso per un motivo preciso: guardando il progetto viene naturale leggere ogni percorso dalla cartella principale sito/. Il browser, invece, usa come punto di partenza la cartella della pagina che contiene il link.
- 1
Partiamo da
sito/index.html. - 2
Vogliamo arrivare a
sito/chi-siamo.html. - 3
Entrambi i file sono nella stessa cartella. Non serve salire o entrare: basta scrivere direttamente il nome del file.
- 1
Partiamo da
sito/index.html. - 2
Vogliamo arrivare a
sito/blog/primo-post.html. - 3
Il file di destinazione è dentro una sottocartella. Dobbiamo prima entrare in
blog/scrivendo il suo nome, poi il nome del file.
- 1
Partiamo da
sito/blog/primo-post.html. - 2
Vogliamo arrivare alla home principale
sito/index.html. - 3
Dobbiamo prima uscire da
blog/per salire asito/. Usiamo../per salire di una cartella, dove troviamo subitoindex.html.
- 1
Partiamo da
sito/blog/primo-post.html. - 2
Vogliamo arrivare all'immagine
sito/immagini/logo.png. - 3
Prima usciamo da
blog/usando../. Una volta arrivati asito/, entriamo inimmagini/e prendiamologo.png.
- 1
Partiamo da
sito/blog/primo-post.html. - 2
Vogliamo arrivare alla home del blog
sito/blog/index.html. - 3
Entrambi sono dentro la cartella
blog/. Non dobbiamo uscire con../: basta indicare direttamente il nome del file.
blog/index.html significa "la cartella blog dentro quella in cui sono adesso". /blog/index.html, con la barra davanti, significa "parti dalla radice del sito, ovunque io mi trovi". Il percorso dalla radice è più comodo per i menu di navigazione, perché funziona identico da qualsiasi pagina.
Aprire in una nuova scheda
L'attributo target="_blank" apre la destinazione in una scheda nuova, lasciando aperta la pagina di partenza.
<a href="https://github.com" target="_blank" rel="noopener noreferrer">
Apri GitHub in una nuova scheda
</a>L'attributo rel="noopener" impedisce alla pagina di destinazione di manipolare quella di partenza tramite JavaScript; noreferrer evita anche di comunicarle da dove arriva il visitatore. I browser recenti applicano noopener da soli con target="_blank", ma scriverlo resta l'abitudine corretta e copre i browser più vecchi.
target="_blank"Aprire schede a raffica toglie all'utente il controllo del pulsante "indietro". Usalo per i link esterni o per documenti da consultare a lato, mai per la navigazione interna al tuo sito.
Scrivere un buon testo di link
Chi usa uno screen reader può chiedere l'elenco di tutti i link della pagina, letti fuori dal contesto. Una lista di dodici voci "clicca qui" è inutilizzabile.
| Da evitare | Meglio |
|---|---|
| Per il listino clicca qui. | Consulta il listino prezzi 2026. |
| Leggi di più | Leggi l'articolo sulla semantica HTML |
Il testo del link deve descrivere la destinazione anche letto da solo. È la regola di accessibilità sui link, e vale anche come buona pratica SEO.
Le pagine ora si parlano tra loro. Aggiungiamo il contenuto visivo.
8. Immagini e contenuti multimediali
Le immagini si inseriscono con <img>, un tag vuoto: non racchiude nulla e non ha tag di chiusura, quindi tutte le informazioni passano dagli attributi.
<img src="/images/gatto-rosso.webp"
alt="Gatto rosso addormentato su un divano grigio"
width="800" height="600">| Attributo | Cosa fa | Obbligatorio? |
|---|---|---|
| src | Il percorso del file immagine. Segue le stesse regole dei link del capitolo 7. | Sì |
| alt | Il testo alternativo, letto quando l'immagine non si vede. | Sì |
| width height | Dimensioni reali in pixel del file. | Fortemente consigliati |
| loading | Con lazy l'immagine viene scaricata solo quando serve. | No |
Scrivere l'alt giusto
L'attributo alt viene letto dagli screen reader, appare se il file non si carica e viene usato dai motori di ricerca. Non esiste un testo "giusto" in assoluto: dipende dal ruolo che l'immagine ha nella pagina.
- L'immagine porta informazione → descrivi l'informazione:
alt="Grafico: le vendite crescono del 30% nel 2025". - L'immagine è dentro un link o un pulsante → descrivi la destinazione, non il disegno:
alt="Torna alla home", nonalt="logo". - L'immagine è puramente decorativa → lascia l'attributo vuoto:
alt="". Così lo screen reader la salta, invece di leggere il nome del file. - Il testo è già scritto accanto all'immagine →
alt="", per non far ripetere due volte la stessa cosa.
alt non è come lasciarlo vuotoSe scrivi alt="" dichiari "questa immagine è decorativa, ignorala". Se invece l'attributo manca del tutto, il risultato dipende dallo screen reader: può arrivare a leggere il nome del file, con risultati tipo «immagine dsc underscore 0042 punto jpg». Scrivi sempre alt, anche quando è vuoto.
Esempio interattivo
Tre casi: ciò che vedi e ciò che comunica HTML
Seleziona un caso e confronta ciò che appare a schermo con ciò che comunica il codice HTML.
altChiediti: "Se dovessi descrivere questa immagine a qualcuno al telefono, cosa direi?". Se l'immagine porta informazione (grafico, fotografia, diagramma), descrivila in poche parole. Se è puramente decorativa, lascia alt="".
Perché indicare width e height
Il browser disegna la pagina prima di aver finito di scaricare le immagini. Se non sa quanto spazio riservare, dispone il testo e poi lo fa saltare via quando l'immagine arriva: è il fastidioso layout shift, che ti fa perdere il punto in cui stavi leggendo. Indicando le dimensioni reali del file, lo spazio viene riservato subito.
width e height dichiarano le dimensioni native del file, così il browser conosce le proporzioni. Quanto grande apparirà davvero a schermo lo decidi con il CSS.
Quale formato scegliere
- WebP / AVIF: la scelta predefinita oggi. Stessa qualità di JPEG e PNG con file molto più leggeri.
- JPEG: fotografie, quando serve la massima compatibilità.
- PNG: immagini con sfondo trasparente o grafica a tinte piatte.
- SVG: loghi, icone e diagrammi. È un formato vettoriale: resta nitido a qualsiasi dimensione e pesa pochissimo.
Immagine con didascalia: <figure>
Quando l'immagine ha una didascalia, non metterla in un <p> qualsiasi: non ci sarebbe alcun legame tra le due. Usa <figure> per raggruppare e <figcaption> per la didascalia.
<figure>
<img src="/immagini/schema-client-server.png"
alt="Il browser invia una richiesta al server, che risponde con la pagina"
width="600" height="400" loading="lazy">
<figcaption>Figura 1 — Il ciclo richiesta/risposta tra client e server.</figcaption>
</figure>La didascalia descrive l'immagine per chi la vede; alt la sostituisce per chi non la vede. Sono due testi diversi con due scopi diversi: evita di copiare l'uno nell'altro.
Video e audio
Video e audio funzionano allo stesso modo, con l'attributo controls che mostra i comandi di riproduzione:
<video src="/media/demo.mp4" controls width="640" poster="/media/anteprima.jpg">
Il tuo browser non supporta i video. <a href="/media/demo.mp4">Scarica il file</a>.
</video>Il testo dentro il tag appare solo se il browser non riesce a riprodurre il file. L'attributo poster indica l'immagine da mostrare prima dell'avvio. Evita autoplay: un video che parte da solo con l'audio è il modo più rapido per far chiudere la pagina.
Testo e immagini sono a posto. Passiamo a organizzare le informazioni in elenchi.
9. Le liste
Nel linguaggio di tutti i giorni, una "lista" fa pensare alla lista della spesa o a una lista di cose da fare. Sul web, però, il concetto è molto più ampio: qualsiasi gruppo di elementi correlati e dello stesso tipo è una lista.
Un menu di navigazione è una lista di link, una galleria e-commerce è una lista di prodotti, e i post di un social network sono una lista di messaggi. Raggrupparli con i tag corretti aiuta i browser e le tecnologie assistive a interpretare la pagina nel modo corretto.
Vediamo ora come sono fatti i tag per creare e personalizzare questi elenchi.
Lista non ordinata: <ul>
Quando l'ordine degli elementi non cambia il significato. Il contenitore è <ul> (unordered list), ogni voce è un <li> (list item).
<ul>
<li>Farina</li>
<li>Zucchero</li>
<li>Uova</li>
</ul>Lista ordinata: <ol>
Quando l'ordine conta: istruzioni, classifiche, passaggi. La numerazione la gestisce il browser, tu non scrivi i numeri.
<ol>
<li>Accendi il forno a 180 °C</li>
<li>Mescola gli ingredienti</li>
<li>Inforna per 40 minuti</li>
</ol>Su <ol> puoi usare start="5" per iniziare da un numero diverso, reversed per contare all'indietro e type="a" per numerare con le lettere.
Liste dentro liste
Qui si annida l'errore più comune. La lista figlia va messa dentro il <li> a cui appartiene, non tra un <li> e l'altro:
<ul>
<li>Bevande
<ul>
<li>Acqua</li>
<li>Vino</li>
</ul>
</li>
<li>Dolci</li>
</ul><ul> e <ol> vanno solo <li>Un <div>, un <p> o del testo libero come figli diretti di una lista non sono validi. Qualsiasi contenuto va prima messo dentro un <li>, che a sua volta può contenere quello che vuoi.
Lista di descrizioni: <dl>
Per coppie termine/spiegazione: glossari, FAQ, schede tecniche. Il contenitore è <dl>, il termine <dt>, la descrizione <dd>.
<dl>
<dt>URL</dt>
<dd>L'indirizzo univoco di una risorsa sul web.</dd>
<dt>DOM</dt>
<dd>L'albero che il browser costruisce leggendo l'HTML.</dd>
</dl>Un <dt> può avere più <dd> (un termine con più significati), e più <dt> possono condividere un <dd> (sinonimi).
Il caso pratico: un menu di navigazione
Un menu è una lista di link. Scritto così, uno screen reader annuncia «lista di 3 elementi» e permette di saltarla in blocco.
<ul>
<li><a href="/it/">Home</a></li>
<li><a href="/servizi/">Servizi</a></li>
<li><a href="/it/contatti/">Contatti</a></li>
</ul>I pallini e l'incolonnamento verticale si tolgono con il CSS: l'aspetto da barra orizzontale è una scelta grafica, la lista resta la struttura corretta.
Le liste organizzano dati in una dimensione. Quando le dimensioni diventano due, servono le tabelle.
10. Le tabelle
Una tabella non è un rettangolo con delle linee. È un modo di organizzare informazioni che hanno senso solo incrociando una riga e una colonna: il prezzo di un piano, l'orario di un treno, il confronto tra due abbonamenti. Se togli quel numero dalla griglia e continua a stare in piedi da solo, probabilmente la tabella non serviva.
Il contenitore è <table>. Dentro ci sono le righe (<tr>). In ogni riga stanno le celle: <th> dà un nome a una colonna o a una riga, <td> tiene il dato. Il titolo della tabella è <caption>. <thead> e <tbody> separano la testa dai dati.
Negli anni Novanta si costruivano i layout con tabelle invisibili. Oggi è un errore grave: uno screen reader annuncia righe e colonne che non esistono concettualmente, e la pagina diventa impossibile da adattare agli schermi piccoli. Per il layout esistono il CSS e i tag semantici del capitolo 12.
Chi guarda incrocia riga e colonna con gli occhi. Chi ascolta sente le celle una dopo l'altra. Per questo su ogni <th> si mette scope: lo screen reader può dire «Base, prezzo: 9,99 euro» invece di un elenco di numeri. Il widget sotto riprende questi quattro punti.
Esempio interattivo
Una tabella, pezzo per pezzo
Gli stessi quattro punti, visti uno alla volta.
<table> <caption>Piani 2026</caption> <tr> <th>Piano</th> <th>Prezzo</th> <th>Spazio</th> </tr> <tr> <td>Base</td> <td>9,99 €</td> <td>10 GB</td> </tr> </table>
<table> <caption>Piani 2026</caption> <thead> <tr> <th>Piano</th> <th>Prezzo</th> </tr> </thead> <tbody> <tr> <th>Base</th> <td>9,99 €</td> </tr> </tbody> </table>
<table> <tr> <th scope="col">Piano</th> <th scope="col">Prezzo</th> </tr> <tr> <th scope="row">Base</th> <td>10 €</td> </tr> </table>
<!-- una pagina, non dei dati --> <table> <tr> <td>Logo</td> <td>Menu</td> <td>Articolo</td> </tr> </table>
| Piano | Prezzo | Spazio |
|---|---|---|
| Base | 9,99 € | 10 GB |
| Premium | 14,99 € | 100 GB |
| Piano | Prezzo |
|---|---|
| Base | 9,99 € |
| Premium | 14,99 € |
| Piano | Prezzo |
|---|---|
| Base | 10 € |
| Logo | Menu | Articolo |
9,99 € da solo non è «un prezzo». È il prezzo del piano Base. Se il numero ha ancora senso dopo che lo togli dalla griglia, probabilmente la tabella non serve.
<th> dà il nome. <td> tiene il fatto.<caption> è il titolo della tabella. <thead> è la riga di testa. <tbody> sono i dati. Un <tr> è una riga. Anche la prima colonna può essere un <th>: dà il nome alla riga.
scope="col" su Piano e Prezzo: quel nome vale per la colonna sotto. scope="row" su Base: quel nome vale per la riga a destra. Così 10 € non è un numero perso: è il prezzo del piano Base.
Logo, menu e articolo non sono una riga di dati. Lo screen reader annuncerà comunque tre colonne. Per il layout usa il CSS e i tag semantici del capitolo 12.
La struttura completa
| Tag | Ruolo |
|---|---|
| <table> | Il contenitore dell'intera tabella. |
| <caption> | Il titolo della tabella. Va subito dopo <table> e dice a chi ascolta di cosa parla. |
| <thead> | La riga (o le righe) di intestazione. |
| <tbody> | Il corpo con i dati. |
| <tfoot> | Riga finale di riepilogo, per esempio i totali. |
| <tr> | Una riga (table row). Contiene le celle. |
| <th> | Cella di intestazione: dà il nome a una colonna o a una riga. |
| <td> | Cella di dato (table data). |
Sulle celle vanno anche tre attributi. Non sono tag: sono coppie nome="valore" scritte nel tag di apertura.
| Attributo | Su quale tag | Ruolo |
|---|---|---|
| scope | <th> | scope="col" nomina una colonna; scope="row" nomina una riga. Serve a chi ascolta, non a chi guarda. |
| colspan | <th> o <td> | Quante colonne occupa quella cella. colspan="2" ne copre due. |
| rowspan | <th> o <td> | Quante righe occupa quella cella. rowspan="2" ne copre due. |
L'attributo che rende accessibile una tabella
Come hai visto nel widget: scope="col" o scope="row" su ogni <th>. Due parole per cella, e l'elenco di numeri diventa una frase.
Unire più celle
colspan estende una cella su più colonne, rowspan su più righe:
<tr>
<td colspan="2">Questa cella occupa due colonne</td>
<td>Normale</td>
</tr>Usali con parsimonia: le tabelle con troppe celle unite diventano difficili da leggere e da annunciare correttamente.
Una tabella non si restringe oltre un certo limite. La soluzione standard è racchiuderla in un contenitore che scorre in orizzontale — <div class="table-wrapper"> con overflow-x: auto nel CSS — invece di lasciarla sfondare la pagina.
Hai imparato tutti i mattoni di contenuto. Adesso la domanda diventa: come li si raggruppa? Partiamo dai contenitori che non significano nulla, per capire perché servono quelli che invece significano qualcosa.
11. div e span: i contenitori neutri
Tutti i tag visti finora dicono qualcosa: <p> è un paragrafo, <ul> è un elenco, <th> è un'intestazione. Ne esistono due che non dicono nulla, ed è esattamente il motivo per cui servono.
<div>è un contenitore di blocco senza significato.<span>è un contenitore in linea senza significato.
Riconosci la distinzione: è quella del capitolo 5. Un <div> si comporta come un <p> (va a capo, prende tutta la larghezza), un <span> come uno <strong> (resta nella riga).
A cosa servono
A raggruppare elementi per potervi agganciare qualcosa — quasi sempre un class per il CSS, a volte un id per JavaScript — quando quel raggruppamento non ha un significato proprio da comunicare. Il widget sotto mostra i quattro punti.
Esempio interattivo
div e span
Una scatola a blocco, una parola nella frase, i due insieme, e l'errore di usare un div al posto di un titolo.
<div> <h3>Tazza</h3> <p>Ceramica, 350 ml.</p> </div>
<p> Prezzo: <span>12,90 €</span> </p>
<div> <h3>Tazza</h3> <p> Prezzo: <span>12,90 €</span> </p> </div>
<div>Come si scrive l'HTML</div> <h1>Come si scrive l'HTML</h1>
Tazza
Ceramica, 350 ml.
Prezzo: 12,90 €
Tazza
Prezzo: 12,90 €
Come si scrive l'HTML
Come si scrive l'HTML
<div> è una scatola. Non dice cosa c'è dentro.Prende tutta la riga, come un paragrafo. Il titolo e il testo restano titolo e testo. Il <div> serve solo a tenerli insieme, per esempio per il CSS.
<span> è una parola nella frase. Non dice cosa significa.Non va a capo. Marca «12,90 €» e il resto della riga continua accanto. Serve se vuoi agganciarci un class, non se la parola è importante: per quello c'è <strong>.
<div> avvolge la scheda. Lo <span> avvolge il prezzo.Togli il CSS e la pagina dice le stesse cose: tazza, prezzo. I due tag non aggiungono significato. Aggiungono solo un appiglio.
<div>. La seconda è un <h1>.Stesse parole. Solo la seconda è un titolo: entra nell'indice, Google e gli screen reader la trovano. Un <div> non diventa un titolo nemmeno se lo fai grande col CSS.
Togli il CSS e la pagina resta identica: sono contenitori a significato zero.
Chiediti: «se rimuovessi questo tag, l'utente perderebbe un'informazione?». Se la risposta è no ed esisteva solo per la grafica, <div> è la scelta giusta. Se la risposta è sì, ti serve un tag che quel significato lo esprima davvero.
L'errore da non fare: la "divite"
Poiché <div> funziona sempre e non dà mai errore, la tentazione è costruirci l'intera pagina:
<div class="header">
<div class="nav">...</div>
</div>
<div class="main">
<div class="articolo">
<div class="titolo">Come si scrive l'HTML</div>
<div class="testo">...</div>
</div>
</div>A schermo, con il CSS giusto, questa pagina può risultare identica a una scritta bene. Ma per tutto ciò che non ha occhi è una distesa di scatole anonime: il browser non sa qual è il contenuto principale, Google non capisce dove inizia l'articolo, e uno screen reader non può offrire nessuna scorciatoia perché non c'è niente da annunciare. Nota anche che <div class="titolo"> non è un titolo: non compare in nessun indice del documento, mentre un <h1> sì.
<div> e <span> sono l'ultima scelta, non la prima. Prima cerca il tag che descrive ciò che stai scrivendo; se e solo se non esiste, usa un contenitore neutro.
Il capitolo che segue ti dà i tag da cercare prima di ripiegare sul <div>.
12. HTML semantico: la struttura della pagina
HTML5 mette a disposizione una serie di tag che funzionano esattamente come un <div> — sono contenitori di blocco — con una differenza decisiva: dichiarano il ruolo della porzione di pagina che racchiudono.
I tag di struttura
| Tag | Cosa racchiude | Quanti per pagina |
|---|---|---|
| <header> | L'intestazione: logo, titolo, menu. Può stare anche dentro un <article>. | Uno principale, più interni |
| <nav> | Un blocco di link di navigazione importanti. | Più di uno (menu, briciole di pane) |
| <main> | Il contenuto specifico di questa pagina, escluso ciò che si ripete ovunque. | Uno solo |
| <article> | Un contenuto che sta in piedi da solo: un post, una recensione, una scheda prodotto. | Quanti servono |
| <section> | Una parte tematica del documento, sempre introdotta da un titolo. | Quante servono |
| <aside> | Contenuto collaterale: barra laterale, box di approfondimento, articoli correlati. | Quanti servono |
| <footer> | Chiusura: copyright, contatti, link legali. Anche interno a un <article>. | Uno principale, più interni |
Una pagina completa
Ecco come si incastrano. Confronta questa struttura con la distesa di <div> del capitolo precedente: il risultato a schermo può essere lo stesso, l'informazione trasmessa no. Clicca una zona della pagina o una riga del codice.
Esempio interattivo
La pagina, zona per zona
Ogni scatola è un <div> che ha imparato a dire chi è.
Il blog di Codedge
Home · Blog · Contatti
Come si scrive un HTML pulito
Prima il contenuto, poi la grafica.
Articoli correlati
<header> è l'intestazione.Logo, titolo del sito, a volte il menu. Può stare anche dentro un articolo. A schermo è una fascia in alto: per il browser è «qui inizia la pagina».
<nav> è il menu, non un elenco qualsiasi.Solo i link con cui ci si muove nel sito. Una lista della spesa resta una <ul>. Chi ascolta può chiedere: «portami al menu».
<main> è il contenuto di questa pagina.Uno solo. Dentro ci stanno l'articolo e, se serve, la colonna a lato. Il menu e il copyright stanno fuori: si ripetono su ogni pagina.
<article> sta in piedi da solo.Un post, una recensione, una scheda. Se lo stacchi dalla pagina e lo pubblichi altrove, ha ancora senso. Per questo non è un <div>.
<aside> è a lato del discorso.Articoli correlati, un box di approfondimento. Utile, ma se lo togli l'articolo principale resta intero.
<footer> chiude.Copyright, contatti, link legali. Come l'<header>, può stare anche in fondo a un singolo articolo.
<article>, <section> o <div>?
È il dubbio ricorrente. Rispondi in ordine a queste tre domande:
- Questo blocco avrebbe senso pubblicato da solo, staccato dal resto della pagina (in un feed RSS, condiviso su un social)? Se sì →
<article>. - Altrimenti: è una parte tematica con un suo titolo? Se sì →
<section>. - Altrimenti: serve solo per la grafica →
<div>.
<section> senza titolo è quasi sempre un <div>Il tag <section> serve a marcare una sezione dell'indice del documento: se non c'è un <h2>–<h6> che la introduce, la sezione non ha nome e non stai comunicando nulla. In quel caso usa un <div>, che è più onesto.
Il vantaggio concreto: le scorciatoie di navigazione
<header>, <nav>, <main>, <aside> e <footer> sono landmark: punti di riferimento che gli screen reader elencano su richiesta. Chi non vede può saltare direttamente al contenuto principale invece di riascoltare il menu su ogni pagina del sito. Con i <div> questa possibilità semplicemente non esiste.
Lo stesso principio vale per chi naviga da tastiera. Mettendo come primo elemento del <body> un link che punta al <main>, offri la stessa scorciatoia:
<a href="#contenuto" class="salta-al-contenuto">Vai al contenuto</a>
...
<main id="contenuto"> ... </main>La pagina è strutturata e leggibile. Resta un'ultima cosa che non sa fare: ricevere qualcosa dall'utente.
13. I form: raccogliere dati dall'utente
Finora la pagina parla e l'utente ascolta. Con i moduli — form — il flusso si inverte: ricerche, login, iscrizioni, ordini, commenti passano tutti da qui.
Il contenitore <form>
<form action="/iscrizione" method="post"> ... </form>action: l'indirizzo a cui vengono spediti i dati.method: come vengono spediti.getli accoda all'URL, restando visibili nella barra degli indirizzi: va bene per una ricerca, che così è condivisibile e memorizzabile.postli invia nel corpo della richiesta, fuori dall'URL: obbligatorio per password, dati personali e qualsiasi cosa che modifichi qualcosa sul server.
HTML costruisce il modulo e lo spedisce. Ricevere i dati, controllarli e salvarli richiede un programma sul server (in PHP, Python, Node.js…) oppure del JavaScript. Se apri un form dal tuo computer e premi Invia, non succederà nulla di utile: è normale.
Tre cose da capire prima di tutti i tipi di campo: type cambia il campo, la <label> gli dà un nome cliccabile, name è ciò che parte verso il server. Il widget sotto le mostra.
Esempio interattivo
Un campo, tre regole
A destra puoi scrivere e cliccare. Non parte niente: è solo per vedere come funziona.
<input type="text"> <input type="email"> <input type="password">
<label for="email">Email</label> <input type="email" id="email">
<label for="con-name">Con name</label> <input id="con-name" name="email"> <label for="senza-name">Senza name</label> <input id="senza-name"> <button>Invia</button>
<input placeholder="Email"> <label for="ok">Email</label> <input id="ok">
type.Scrivi nei tre campi. Il primo è testo. Il secondo vuole una @. Il terzo nasconde le lettere. Non sono tre tag diversi: è <input> con tre attributi.
Il cursore entra lo stesso. for e id sono lo stesso nome: così l'etichetta e il campo sono una cosa sola. Senza questo legame è una scatola muta.
Parte solo il campo con name. L'altro sparisce, senza errore. id serve alla label. name serve all'invio. Servono entrambi.
Scrivi nel primo campo: «Email» sparisce. Nel secondo la parola resta sopra, sempre. Il placeholder è un esempio di formato, non il nome del campo.
I campi: <input> e il suo type
<input> è un tag vuoto che cambia completamente aspetto e comportamento in base all'attributo type:
| type | Cosa produce |
|---|---|
| text | Campo di testo su una riga. È il valore predefinito. |
| Campo email: su smartphone mostra la tastiera con la @ e il browser verifica il formato. | |
| password | Nasconde i caratteri digitati. |
| number | Numeri, con frecce di incremento e attributi min e max. |
| tel | Numeri di telefono: apre il tastierino numerico. |
| date | Selettore di data fornito dal browser. |
| checkbox | Casella con scelta indipendente (accetto i termini). |
| radio | Scelta unica tra opzioni: si escludono a vicenda. |
| file | Selezione di un file da caricare. |
| submit | Pulsante che invia il modulo. |
Scegliere il type corretto non è pignoleria: da solo ti dà la tastiera giusta su mobile, un controllo di validità e, per le date, un calendario che non devi programmare.
Ogni campo ha bisogno di una <label>
Un campo senza etichetta è una casella vuota di cui nessuno conosce lo scopo. L'etichetta si collega al campo facendo combaciare il suo for con l'id del campo:
<label for="email">Indirizzo email</label>
<input type="email" id="email" name="email">Il collegamento produce due effetti: lo screen reader annuncia «indirizzo email, campo di testo» quando l'utente ci arriva, e un clic sull'etichetta porta il cursore dentro il campo, allargando l'area cliccabile — un vantaggio concreto su schermo touch.
placeholder non sostituisce la labelIl testo grigio dentro il campo sparisce appena si inizia a scrivere: chi si distrae non ha più modo di sapere cosa andava scritto lì, e il contrasto è spesso troppo basso per essere leggibile. Usa il placeholder solo per un esempio di formato, e metti sempre una <label> visibile.
L'attributo name: il più importante di tutti
Quando il modulo viene inviato, ogni campo spedisce una coppia nome = valore. Il nome è quello dell'attributo name: è la chiave con cui il server ritrova il dato.
name, il campo non viene inviatoNessun errore, nessun avviso: il dato semplicemente non parte. È la causa numero uno dei form "che non funzionano". id serve alla label, name serve all'invio: servono entrambi.
Gli altri campi
<textarea>: testo su più righe. Non è un input, ha un tag di chiusura e il valore iniziale si scrive tra i due tag.<select>con<option>: menu a tendina. Ogni opzione ha un attributovalueche è ciò che viene realmente inviato.<button>: il pulsante. Dentro un form il tipo predefinito èsubmit: se ti serve un pulsante che non invia nulla, scrivi esplicitamentetype="button".<fieldset>con<legend>: raggruppa campi collegati e dà un nome al gruppo. Indispensabile con iradio, altrimenti non si capisce a quale domanda rispondono.
La validazione che non richiede codice
Il browser sa già rifiutare un modulo incompleto o malformato, senza una riga di JavaScript:
| Attributo | Vincolo imposto |
|---|---|
| required | Il campo non può restare vuoto. |
| minlength maxlength | Lunghezza minima e massima del testo. |
| min max | Valore minimo e massimo per numeri e date. |
| pattern | Il testo deve rispettare uno schema (es. un CAP di 5 cifre). |
| autocomplete | Permette al browser di compilare in automatico nome, email, indirizzo. |
Questi controlli migliorano l'esperienza dell'utente, ma vanno sempre ripetuti sul server: chiunque può aggirare la validazione del browser.
Un modulo completo
<form action="/contatti" method="post">
<label for="nome">Nome e cognome</label>
<input type="text" id="nome" name="nome" required autocomplete="name">
<label for="email">Email</label>
<input type="email" id="email" name="email" required
placeholder="[email protected]" autocomplete="email">
<label for="motivo">Motivo del contatto</label>
<select id="motivo" name="motivo">
<option value="info">Richiesta di informazioni</option>
<option value="preventivo">Preventivo</option>
<option value="assistenza">Assistenza</option>
</select>
<fieldset>
<legend>Come preferisci essere ricontattato?</legend>
<input type="radio" id="via-email" name="contatto" value="email" checked>
<label for="via-email">Via email</label>
<input type="radio" id="via-telefono" name="contatto" value="telefono">
<label for="via-telefono">Al telefono</label>
</fieldset>
<label for="messaggio">Messaggio</label>
<textarea id="messaggio" name="messaggio" rows="5" required></textarea>
<input type="checkbox" id="privacy" name="privacy" required>
<label for="privacy">Ho letto l'informativa sulla privacy</label>
<button type="submit">Invia richiesta</button>
</form>Osserva i due radio: hanno id diversi (devono essere unici) ma lo stesso name. È proprio il name condiviso a renderli alternativi tra loro: se glielo cambi, diventano due scelte indipendenti e l'utente potrà selezionarle entrambe.
Il <body> ora sa fare tutto. Torniamo all'inizio del file, dove si decide come la pagina si presenta al mondo.
14. L'head: metadati, SEO e anteprime social
Nel capitolo 3 abbiamo definito il <head> come la parte invisibile del documento. Non contiene ciò che si legge nella pagina, ma tutto ciò che serve per leggerla: come interpretare i caratteri, come comportarsi sui telefoni, quali fogli di stile caricare, cosa mostrare su Google e nelle chat.
Le tre righe che non possono mancare
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Corso di HTML per principianti | Codedge</title>charset: dichiara la codifica dei caratteri. Senza, accenti ed emoji diventano simboli incomprensibili. Va scritto tra le primissime righe dell'head.viewport: dice al telefono di usare la larghezza reale dello schermo. Senza questa riga, il cellulare finge di essere un desktop e mostra la pagina rimpicciolita e illeggibile.title: il titolo della scheda del browser, il nome del segnalibro e il titolo blu nei risultati di ricerca. È diverso dall'<h1>, che sta nel body: tienilo entro i 60 caratteri.
Queste righe non si vedono nel body. Clicca una riga dell'head: si accende il posto dove finisce.
Esempio interattivo
Tre righe, tre posti
<title> va sulla scheda. La description va su Google. Open Graph va nella chat.
Non è l'<h1> del body. È il testo in alto nel browser e, di solito, il titolo blu su Google.
Non decide la posizione in classifica. Decide se qualcuno clicca. Circa 150 caratteri.
Senza, la chat mostra solo l'indirizzo. L'immagine vuole un URL intero, con https://.
Farsi trovare: i metadati per i motori di ricerca
<meta name="description" content="Guida pratica all'HTML: struttura, tag semantici, link, immagini e form spiegati passo passo.">
<link rel="canonical" href="https://codedge.it/it/tutorial/html-fondamentali/">description: il riassunto di circa 150 caratteri che compare sotto il titolo nei risultati di ricerca. Non influenza direttamente il posizionamento, ma decide se qualcuno cliccherà.canonical: indica l'indirizzo ufficiale della pagina. Se lo stesso contenuto è raggiungibile da più URL, evita che venga considerato duplicato.
L'anteprima quando si condivide un link
Quando incolli un indirizzo su WhatsApp, LinkedIn o Slack e compare un riquadro con titolo, descrizione e immagine, quei dati arrivano dai metadati Open Graph. Se non li scrivi, l'anteprima sarà un link nudo o un ritaglio casuale della pagina.
<meta property="og:title" content="Corso di HTML per principianti">
<meta property="og:description" content="Struttura, semantica, link, immagini e form spiegati passo passo.">
<meta property="og:image" content="https://codedge.it/immagini/anteprima.jpg">
<meta property="og:url" content="https://codedge.it/it/tutorial/html-fondamentali/">
<meta property="og:type" content="article">og:image vuole un indirizzo assoluto, con https://: i social scaricano l'immagine dai loro server e un percorso relativo non significherebbe nulla per loro. La misura standard è 1200×630 pixel.
Collegare CSS e JavaScript
Nell'head si dichiarano anche i file esterni che la pagina deve usare:
<link rel="stylesheet" href="/css/stile.css">
<script src="/js/app.js" defer></script>Il foglio di stile va nell'head perché serve prima che la pagina venga disegnata. Per gli script, l'attributo defer dice al browser di scaricarli in parallelo e di eseguirli solo a pagina pronta: eviti di bloccare la visualizzazione e ti assicuri che gli elementi da manipolare esistano già.
Completa l'head anche l'icona della scheda: <link rel="icon" href="/favicon.ico">.
L'head pronto da copiare
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Titolo della pagina | Nome del sito</title>
<meta name="description" content="Riassunto della pagina in circa 150 caratteri.">
<link rel="canonical" href="https://esempio.it/pagina/">
<meta property="og:title" content="Titolo della pagina">
<meta property="og:description" content="Riassunto della pagina.">
<meta property="og:image" content="https://esempio.it/anteprima.jpg">
<meta property="og:url" content="https://esempio.it/pagina/">
<link rel="icon" href="/favicon.ico">
<link rel="stylesheet" href="/css/stile.css">
</head>Hai visto l'intero percorso: dallo scheletro del file ai tag di contenuto, dalla struttura semantica ai moduli, fino ai metadati. Prima di passare alla pratica, vediamo gli errori che vale la pena evitare fin dall'inizio.
15. I 5 errori semantici più comuni (e come evitarli)
Per concludere in modo pratico, ecco una rassegna degli errori più comuni commessi dai principianti e i consigli di sviluppo per correggerli subito.
Il tag `<br>` serve unicamente per andare a capo all'interno di un testo (come in una poesia o in un indirizzo postale). Se vuoi distanziare due paragrafi o due scatole grafiche, usa la proprietà `margin` del CSS. Non forzare il layout con HTML.
Un elemento in linea come `<span>` o `<strong>` non dovrebbe mai contenere elementi a blocco come `<div>` o `<h2>`. Rispetta sempre il flusso logico del browser per non rompere il rendering.
Usare un `<h3>` solo perché di default è più piccolo di un `<h2>`, distruggendo la struttura gerarchica del documento, è un pessimo errore. Usa i tag corretti in ordine numerico logico, e modifica la loro dimensione visiva usando la proprietà CSS `font-size`.
Lasciare le immagini senza l'attributo `alt` (o scriverci il nome del file es. `alt="logo_nuovo_definitivo2.png"`) è un'abitudine dannosa per la SEO e un incubo per chi naviga tramite screen reader. Scrivi descrizioni brevi, chiare e ricche di significato.
Usare il tag `<blockquote>` per indentare un testo a sinistra o `<address>` solo per rendere le parole in corsivo è un anti-pattern. I tag servono per descrivere cosa sono i dati, non come appaiono.
16. Sintassi rapida (Cheat Sheet)
Ecco i tag semantici essenziali da ricordare per strutturare correttamente i contenuti:
| Tag | Ruolo Semantico | Regole di Annidamento |
|---|---|---|
| <header> | Testata principale della pagina o di una sezione. | Solitamente contiene loghi, titoli <h1>-<h6> o navigazione. |
| <nav> | Sezione contenente link di navigazione. | Spesso racchiude una lista ordinata <ol> o non ordinata <ul>. |
| <main> | Contenuto principale e unico del documento. | Deve essercene solo uno per pagina, non va inserito in altri tag semantici. |
| <article> | Contenuto autonomo e indipendente (es. post di blog). | Dovrebbe avere un titolo proprio (<h2>-<h6>). |
| <section> | Sezione generica a tema del documento. | Usare solo se la sezione ha un senso logico e un titolo di intestazione. |
17. Sfida pratica: Mettiti alla prova
Non c'è modo migliore di imparare che sporcarsi le mani. Prova a completare questa piccola sfida nel playground o nel tuo editor prima di passare al quiz:
Crea una struttura per una pagina profilo personale (curriculum) semantica, contenente una testata, una lista di passioni ed un form di contatto accessibile.
Istruzioni passo-passo:- Usa il tag
<header>per racchiudere il tuo nome (in un tag<h1>) ed un sottotitolo descrittivo. - Crea una
<section>con intestazione<h2>dedicata alle tue passioni, elencandone tre in una lista non ordinata<ul>. - Inserisci un modulo
<form>con un campo di input email ed una<textarea>per i messaggi. - Associa correttamente ciascun input a una
<label>visibile usando l'accoppiamento degli attributiforeid.
18. Dove continuare dopo
Hai gettato le fondamenta della tua casa nel web. Ora che padroneggi la struttura, puoi iniziare a decorarla e renderla intelligente. Ecco le tappe naturali del tuo percorso di apprendimento:
- CSS Fondamentali: il passo successivo logico per dare colore, stile e definire il layout spaziale dei tuoi tag HTML.
- VS Code Essenziale: impara a scrivere codice velocemente sfruttando le scorciatoie di Emmet, i suggerimenti automatici e l'ambiente di lavoro ideale.
- DevTools del Browser: scopri come ispezionare il DOM, esplorare gli elementi delle pagine web in tempo reale e diagnosticare i bug.
- Indice Tutorial: torna all'elenco completo per scegliere il tuo prossimo argomento.
19. Verifica la tua preparazione (Quiz)
Metti alla prova quello che hai imparato in questa guida con questo rapido test di 10 domande a scelta multipla.