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. Lo scheletro base (Boilerplate)
Nei capitoli precedenti abbiamo visto la teoria dell'HTML: come ragiona il browser creandone l'albero (il DOM) e le regole per scrivere correttamente i singoli tag. Ora facciamo un passo in avanti: uniamo questi concetti per costruire il nostro primo file reale.
Ogni singola pagina internet ha bisogno di una struttura di partenza fissa per poter essere interpretata dal browser. Questa struttura ripetitiva, una vera e propria "tela bianca", viene chiamata in gergo Boilerplate (o scheletro di base). In VS Code ti basterà digitare ! e premere Invio per generarlo all'istante, ma da bravi sviluppatori dobbiamo capirne ogni singola riga:
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>La mia prima pagina web</title>
</head>
<body>
<!-- Qui scriveremo i contenuti visibili del sito -->
</body>
</html>Come è organizzata la struttura:
<!DOCTYPE html>: è una dichiarazione tecnica. Serve a gridare al browser: "Attenzione, questo è un file HTML moderno (HTML5), leggilo usando gli standard attuali!". Va scritto obbligatoriamente come prima riga, in alto.<html lang="it">: è la scatola radice che contiene tutto il resto. L'attributolang="it"è fondamentale: indica che il testo è in italiano, aiutando i motori di ricerca a indicizzarlo e permettendo agli screen reader di pronunciarlo con la giusta intonazione.- La divisione in due macro-aree: nota come il contenuto dentro
<html>sia diviso in due grandi "scatole cinesi" principali:<head>(La cabina di regia): contiene i metadati, cioè informazioni utili al browser e a Google ma invisibili ai visitatori della pagina (es. la codifica dei caratteriUTF-8per le lettere accentate e le emoji, o il titolo della scheda nel tag<title>).<body>(Il palcoscenico visibile): è il corpo della pagina. Tutto quello che inseriremo in questo blocco verrà visualizzato sullo schermo dell'utente.
Ora che hai impostato il tuo contenitore vuoto, è il momento di entrare nel <body> e iniziare a scoprire il catalogo dei tag: i mattoni effettivi con cui popoleremo la nostra pagina. Partiamo dall'elemento base di qualsiasi comunicazione: la scrittura del 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.
Per capire meglio la sua importanza, pensa alla struttura di una lettera cartacea:
- L'
<head>è la busta della lettera: contiene l'indirizzo del destinatario, il francobollo, il mittente. Sono informazioni fondamentali per far viaggiare la lettera, ma chi la riceve non legge la busta per conoscere il messaggio. - Il
<body>è il foglio di carta interno: contiene il messaggio vero e proprio, le parole scritte, i disegni o gli allegati. È ciò che interessa davvero 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. Partiamo dal caso più comune e frequente in assoluto: del testo.
Perché il testo "nudo" non basta
La prima reazione istintiva è scrivere il testo direttamente dentro il body, andando a capo dove serve:
<body>
Corso di HTML
Questa è la prima frase.
Questa dovrebbe essere una frase separata.
</body>Apri questo file nel browser e vedrai una cosa sola, tutta su una riga:
Corso di HTML Questa è la prima frase. Questa dovrebbe essere una frase separata.Non è un bug. È la regola più importante da capire sul testo in HTML:
Qualsiasi sequenza di spazi, tabulazioni e andate a capo che scrivi nel codice viene compressa dal browser in un unico spazio. Premere Invio nell'editor non manda a capo nella pagina, e mettere venti spazi non allontana di venti spazi.
Questo significa che l'aspetto della pagina non dipende da come formatti il codice, ma solo dai tag che usi. L'indentazione nel file serve a te per leggere, non al browser. Per separare davvero due blocchi di testo servono i tag.
Il paragrafo: <p>
Il tag <p> (paragraph) racchiude un blocco di testo compiuto. Ogni paragrafo occupa la sua riga, va a capo da solo e il browser gli lascia un po' di spazio sopra e sotto.
<body>
<p>Questa è la prima frase.</p>
<p>Questa è una frase separata, in un blocco tutto suo.</p>
</body>Ora i due testi sono davvero due blocchi distinti. Nota che dentro un paragrafo puoi scrivere il testo come vuoi, anche su più righe nel codice: sarà comunque un blocco unico, perché è il tag a definire il blocco, non l'andata a capo.
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. Vale per tutti i blocchi: nessun blocco va dentro un <p>. Il perché lo vedremo nel capitolo 6.
I titoli: da <h1> a <h6>
Un testo lungo fatto solo di paragrafi è illeggibile: serve dividerlo in sezioni con dei titoli. HTML mette a disposizione sei tag di intestazione (heading), da <h1> a <h6>.
Il numero non indica la grandezza del carattere: indica il livello di profondità, esattamente come i numeri di un indice. <h1> è il titolo dell'intera pagina, <h2> apre una sezione principale, <h3> una sotto-sezione di quella sezione, e così via.
<h1>Corso di cucina</h1>
<p>Benvenuto nel corso. Ecco cosa vedremo.</p>
<h2>Gli attrezzi</h2>
<p>Prima di cucinare servono gli strumenti giusti.</p>
<h3>I coltelli</h3>
<p>Ne bastano tre per iniziare.</p>
<h3>Le pentole</h3>
<p>Meglio poche e di buona qualità.</p>
<h2>Le prime ricette</h2>
<p>Iniziamo da qualcosa di semplice.</p>I tag che vedi scritti descrivono questa struttura, che è l'indice della pagina:
Corso di cucina [h1] ← titolo della pagina
│
├── Gli attrezzi [h2] ← sezione
│ ├── I coltelli [h3] ← sotto-sezione
│ └── Le pentole [h3] ← sotto-sezione
│
└── Le prime ricette [h2] ← sezioneQuesta gerarchia non è solo teoria: viene usata da Google per comprendere la struttura dei contenuti e dagli screen reader per permettere alle persone non vedenti di orientarsi e saltare rapidamente 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> che è più piccolo.» Così facendo hai rotto l'indice del documento per un motivo grafico. Usa il tag giusto per la gerarchia e rimpicciolisci con il CSS: sono due problemi diversi, e HTML si occupa solo del primo.
Con titoli e paragrafi si stabilisce l'ossatura generale di una pagina. Tuttavia, spesso nasce la necessità di evidenziare o dare un significato speciale a singole parole o frasi all'interno di un paragrafo (ad esempio per indicare un termine importante o un frammento di codice) senza per questo spezzare la riga e andare a capo. Questo è il compito dei tag in linea, che verranno esaminati nel prossimo capitolo.
5. Marcare le parole: i tag in linea
Nel capitolo precedente sono stati utilizzati tag che creano interi blocchi di testo e vanno a capo automaticamente (come i paragrafi <p> e i titoli). I tag in linea (inline), invece, si inseriscono direttamente all'interno di un testo. Servono a evidenziare o definire una o più parole specifiche senza spezzare la riga o 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 8 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 12. | 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.
A questo punto hai usato tag che occupano una riga intera e tag che restano dentro la riga. Non è una differenza casuale: è la classificazione su cui si regge tutto l'HTML. Vediamola.
6. Blocco e in linea: come il browser dispone gli elementi
Perché due <p> finiscono uno sotto l'altro, mentre due <strong> restano affiancati sulla stessa riga? Perché ogni elemento HTML appartiene, per impostazione predefinita, a una di due categorie.
Elementi di blocco
- Iniziano sempre su una riga nuova e spingono a capo ciò che segue.
- Occupano tutta la larghezza disponibile del loro contenitore, anche se il contenuto è corto.
- Possono contenere altri blocchi e elementi in linea.
Sono blocchi: <p>, <h1>…<h6>, <div>, <ul>, <ol>, <li>, <table>, <form>, <figure>, <hr>, <header>, <nav>, <main>, <article>, <section>, <aside>, <footer>.
Elementi in linea
- Non vanno a capo: scorrono dentro la riga di testo insieme alle parole.
- Occupano solo lo spazio del loro contenuto, non un millimetro in più.
- Devono contenere testo o altri elementi in linea, mai un elemento di blocco.
Sono in linea: <a>, <strong>, <em>, <code>, <span>, <img>, <br>, <abbr>, <input>, <label>.
Prova questo esempio: i due paragrafi si impilano, i due <span> restano attaccati.
<p>Primo blocco: prendo tutta la larghezza.</p>
<p>Secondo blocco: sto sotto al primo.</p>
<p>
<span>Primo in linea.</span>
<span>Secondo in linea: sto sulla stessa riga.</span>
</p>Perché ti serve saperlo adesso
Perché da questa distinzione discende la regola di annidamento che si viola più spesso:
Scrivere <span><h2>Titolo</h2></span> o <p><div>...</div></p> è codice non valido. Il browser non si ferma: riscrive l'albero come gli pare, e ti ritrovi con un risultato che non capisci e un CSS che sembra "non funzionare".
C'è un'eccezione molto importante a questa regola: il tag di collegamento <a>, pur essendo un elemento in linea, può racchiudere interi blocchi (come titoli, paragrafi, o interi <div>). Questo è fondamentale per rendere cliccabile un'intera area o una scheda prodotto, anziché solo il suo testo:
<a href="/prodotti/tazza/">
<h3>Tazza Codedge</h3>
<p>Ceramica smaltata, 350 ml.</p>
</a>È facile confondere le regole di annidamento dell'HTML con l'aspetto grafico degli elementi:
- Le regole dell'HTML (strutturali): Definiscono la validità del codice. Ad esempio, non si può inserire un
<p>(blocco) dentro uno<span>(in linea). Questa gerarchia è fissa ed è quella che determina come il browser interpreta il documento. - Le proprietà del CSS (estetiche): Attraverso la proprietà
display(es.display: blockodisplay: inline) puoi dire al browser di mostrare graficamente uno<span>a tutta larghezza come fosse un blocco, o un paragrafo sulla stessa riga come fosse in linea.
Ricorda: cambiare il comportamento visivo con il CSS non cambia le regole dell'HTML. Anche se applichi display: block a uno <span>, rimane illegale inserire un paragrafo o un titolo al suo interno.
Sai come si scrivono i tag e come si dispongono. Manca un pezzo trasversale: gli attributi che puoi mettere su qualsiasi tag, e che i prossimi capitoli useranno di continuo.
7. 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 però a disposizione anche degli attributi globali (o universali): attributi che puoi scrivere su qualsiasi elemento.
I due più importanti sono id e class, e servono entrambi alla stessa cosa: dare un'etichetta a un elemento, così da poterlo ritrovare più avanti. Cambia solo quante volte quell'etichetta può comparire nella pagina:
id: è come il numero di matricola di uno studente. Appartiene a un solo elemento: nella stessa pagina non possono esistere due elementi con lo stessoid.class: è come dire "studenti della 3A". Può essere ripetuta su quanti elementi vuoi, e un elemento può appartenere a più classi insieme.
Scrivere id o class non cambia né l'aspetto né il comportamento della pagina: il browser non mostra nulla di diverso. Sono nomi che preparano il terreno, e diventano utili quando qualcosa va a cercarli: un link, un foglio di stile CSS o del codice JavaScript.
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.
8. 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:info@sito.it | 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 sempre. Immagina questa struttura di cartelle sul tuo computer:
sito/
├── index.html ← la home
├── chi-siamo.html
├── immagini/
│ └── logo.png
└── blog/
├── index.html ← la home del blog
└── primo-post.htmlUn percorso relativo si legge partendo dalla cartella in cui si trova la pagina che stai scrivendo. Il simbolo ../ significa "sali di una cartella".
| Sei in | Vuoi arrivare a | Scrivi |
|---|---|---|
| index.html | chi-siamo.html | chi-siamo.html |
| index.html | blog/primo-post.html | blog/primo-post.html |
| blog/primo-post.html | index.html (la home) | ../index.html |
| blog/primo-post.html | immagini/logo.png | ../immagini/logo.png |
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.
9. 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="/immagini/gatto.jpg"
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 8. | 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, lo screen reader non sa cosa fare e legge il nome del file, con risultati tipo «immagine dsc underscore 0042 punto jpg». Scrivi sempre alt, anche quando è vuoto.
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.
10. Le liste
Le liste servono ogni volta che hai più elementi dello stesso tipo. Non solo elenchi puntati: i menu di navigazione, le gallerie di prodotti e i risultati di ricerca sono tutti, sotto sotto, liste. Marcarli come tali comunica agli screen reader quanti elementi ci sono ancora da leggere.
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="/">Home</a></li>
<li><a href="/servizi/">Servizi</a></li>
<li><a href="/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.
11. Le tabelle
Una tabella serve per i dati tabellari: informazioni che hanno senso solo incrociando una riga e una colonna. Un listino prezzi, un orario ferroviario, un confronto tra piani di abbonamento.
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 13.
La struttura completa
<table>
<caption>Piani di abbonamento 2026</caption>
<thead>
<tr>
<th scope="col">Piano</th>
<th scope="col">Prezzo mensile</th>
<th scope="col">Spazio</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Base</th>
<td>9,99 €</td>
<td>10 GB</td>
</tr>
<tr>
<th scope="row">Premium</th>
<td>14,99 €</td>
<td>100 GB</td>
</tr>
</tbody>
</table>| 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). |
L'attributo che rende accessibile una tabella
Chi vede la tabella incrocia riga e colonna con lo sguardo. Chi la ascolta, no: sente le celle una dopo l'altra. L'attributo scope su ogni <th> risolve il problema dicendo se quell'intestazione vale per una colonna (scope="col") o per una riga (scope="row").
Con scope impostato, lo screen reader legge «Premium, prezzo mensile: 14,99 euro» invece di un elenco di numeri privi di riferimento. Sono due parole per cella e cambiano completamente l'usabilità.
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.
12. 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 6. 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.
<div class="scheda-prodotto">
<h3>Tazza Codedge</h3>
<p>Ceramica smaltata, 350 ml.</p>
<p>Prezzo: <span class="prezzo-scontato">12,90 €</span></p>
</div>Il <div> esiste solo per dare al CSS un appiglio con cui disegnare il riquadro, lo sfondo e i bordi della scheda. Lo <span> esiste solo per colorare di rosso il prezzo. 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>.
13. 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.
<body>
<header>
<h1>Il blog di Codedge</h1>
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="/contatti/">Contatti</a></li>
</ul>
</nav>
</header>
<main>
<article>
<h2>Come si scrive un HTML pulito</h2>
<p>Pubblicato il <time datetime="2026-03-14">14 marzo 2026</time>.</p>
<section>
<h3>Partire dalla struttura</h3>
<p>Prima il contenuto, poi la grafica.</p>
</section>
<section>
<h3>Scegliere i tag giusti</h3>
<p>Ogni tag ha un significato: usalo per quello.</p>
</section>
</article>
<aside>
<h2>Articoli correlati</h2>
<ul>
<li><a href="/blog/css-base/">Introduzione al CSS</a></li>
</ul>
</aside>
</main>
<footer>
<p>© 2026 Codedge</p>
</footer>
</body><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.
14. 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.
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="nome@esempio.it" 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.
15. 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.
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/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/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.
16. 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.
17. 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. |
18. 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.
19. 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.
20. 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.