HTML
Struttura, testo, link, immagini, media, tabelle e moduli, con il browser accanto al codice
Ogni esempio di questo modulo ha il codice a sinistra e, a destra, quello che mostra un browser vero. Il codice si può modificare: cambia una parola o un tag e l'anteprima si aggiorna da sola. Se sbagli, il pulsante Ripristina riporta tutto com'era. Sui telefoni tocca prima Modifica.
Che cos'è l'HTML
Un linguaggio di marcatura
HTML (HyperText Markup Language) non è un linguaggio di programmazione: non ha variabili, cicli o condizioni. È un linguaggio di marcatura (markup): un modo di aggiungere al testo delle annotazioni, distinte dal testo stesso, che ne descrivono il ruolo. «Questo è un titolo», «questo è un paragrafo», «questa parola è un collegamento».
Il termine viene dalla tipografia. Prima dei computer, i redattori scrivevano a mano sui manoscritti istruzioni per l'autore o per il compositore: «grassetto», «a capo», «titolo di capitolo». Quelle annotazioni erano il markup. In HTML le annotazioni si chiamano tag e si scrivono tra parentesi angolari: <h1>, <p>, <a>.
HTML, XHTML e HTML5
L'HTML ha avuto una storia movimentata. A metà degli anni 2000 il W3C lavorava a XHTML 2.0, una revisione radicale basata su XML: rinunciava alla compatibilità con le pagine esistenti e prevedeva browser molto meno tolleranti, pronti a rifiutare una pagina per un solo errore di sintassi.
Nello stesso periodo un gruppo di sviluppatori di Opera, Mozilla e Apple fonda il WHATWG (Web Hypertext Application Technology Working Group), convinto che quella strada fosse sbagliata per un Web fatto di miliardi di pagine imperfette. Nel 2009 il W3C abbandona XHTML 2.0 e adotta il lavoro del WHATWG, che prende il nome di HTML5. I suoi tre obiettivi:
- specificare senza ambiguità come i browser devono trattare il markup non valido, così che tutti lo correggano allo stesso modo;
- offrire, attraverso JavaScript, una piattaforma aperta e non proprietaria per costruire applicazioni web ricche;
- restare compatibile con il Web esistente.
Oggi l'HTML è un living standard, uno standard «vivo» che evolve continuamente: ogni browser ne supporta un sottoinsieme che cresce nel tempo. Per sapere se una funzione è supportata si consultano caniuse.com e la documentazione di MDN (MDN Web Docs, di Mozilla), il riferimento più affidabile per HTML e CSS.
Per cominciare bastano pochi strumenti:
- Un editor di testo per programmatori: Visual Studio Code è gratuito e il più diffuso. Un file HTML è semplice testo, salvato con estensione
.html. - Un browser, con i suoi strumenti per sviluppatori (F12): la scheda Elementi mostra l'albero della pagina e gli stili applicati.
- Il validatore del W3C, validator.w3.org: controlla che il markup segua le regole dello standard. Validare è stata una delle bandiere del movimento per gli standard web degli anni 2000, ed è ancora un'abitudine eccellente.
La sintassi
Elementi, tag e contenuto
Un documento HTML è fatto di testo e di elementi. Un elemento di solito ha un tag di apertura, un contenuto e un tag di chiusura, che ripete il nome preceduto da una barra.
Attributi ed elementi vuoti
Gli attributi aggiungono informazioni a un elemento e si scrivono nel tag di apertura, nella forma nome="valore", separati da spazi. Alcune regole:
- i valori vanno tra virgolette, doppie o singole. HTML5 tollera valori senza virgolette se non contengono spazi, ma è meglio metterle sempre;
- l'ordine degli attributi non conta;
- gli attributi booleani valgono per la sola presenza:
<input required>. Scrivererequired="false"non li disattiva: per disattivarli bisogna toglierli.
Alcuni elementi non hanno contenuto: sono istruzioni per il browser, come «inserisci qui un'immagine» o «vai a capo». Si chiamano elementi vuoti (void elements) e hanno solo il tag di apertura: <img>, <br>, <hr>, <input>, <meta>, <link>, <source>, <track>, <wbr>.
In XHTML andavano chiusi con una barra finale, <br />. In HTML5 la barra è facoltativa: <br> e <br /> sono equivalenti. Scegli uno stile e usalo sempre.
L'annidamento
Spesso un elemento ne contiene altri. L'elemento che contiene è il genitore (parent), quelli contenuti direttamente sono i figli (children). Gli elementi contenuti a qualsiasi livello sono i discendenti, e al contrario gli elementi che contengono un elemento, a qualsiasi livello, sono i suoi antenati. Elementi con lo stesso genitore sono fratelli (siblings). Questi termini torneranno di continuo nei selettori CSS.
Perché il browser costruisca la gerarchia giusta, gli elementi devono essere annidati correttamente: il tag di chiusura di un figlio deve venire prima di quello del genitore. Come le parentesi in matematica: ( [ ] ) va bene, ( [ ) ] no.
Annidamento corretto
<h1>Share Your <strong>Travels</strong></h1>
Annidamento sbagliato
<h1>Share Your <strong>Travels</h1></strong>
Il browser costruisce dal codice un albero, il DOM (Document Object Model): ogni elemento è un nodo, con il suo genitore e i suoi figli. Nell'esempio apri la scheda Albero DOM e passa sopra i nodi: l'elemento corrispondente si illumina nell'anteprima.
article è il genitore di h2, p e ul, che sono fratelli tra loro; strong è figlio di h2 e discendente di article.
Commenti, spazi e maiuscole
Tre dettagli che fanno la differenza.
- Commenti: tutto quello che sta tra
<!--e-->viene ignorato dal browser. Servono per annotare il codice, ma sono visibili a chiunque apra il sorgente della pagina: mai scriverci password o note riservate. - Spazi bianchi: il browser riduce qualsiasi sequenza di spazi, tabulazioni e a capo a un solo spazio. Andare a capo nel codice non va a capo nella pagina: per quello servono nuovi paragrafi, o in casi rari
<br>. - Maiuscole: i nomi di tag e attributi non distinguono maiuscole e minuscole (
<P>=<p>), ma la convenzione è scrivere tutto in minuscolo.
La struttura di un documento
Il documento più piccolo
Il più piccolo documento HTML5 valido è sorprendentemente corto:
L'elemento title non compare dentro la pagina: il browser lo mostra nella scheda (e nella barra della finestra), lo usa per i preferiti e i motori di ricerca lo mostrano come titolo del risultato. Prova a cambiarlo.
Un documento completo
Il documento minimo funziona perché il browser aggiunge da solo gli elementi che mancano. Nella pratica si scrive sempre la struttura completa:
<!DOCTYPE html> <!-- 1 -->
<html lang="it"> <!-- 2 -->
<head> <!-- 3 -->
<meta charset="utf-8"> <!-- 5 -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Share Your Travels — New York, Central Park</title>
<link rel="stylesheet" href="css/main.css"> <!-- 6 -->
<script src="js/main.js" defer></script> <!-- 7 -->
</head>
<body> <!-- 4 -->
<h1>Il titolo principale va qui</h1>
…
</body>
</html>
1 <!DOCTYPE html>Dice al browser che sta per leggere un documento HTML moderno. Non indica una versione: dice solo «è HTML». Senza, il browser entra in modalità quirks e imita i difetti dei browser degli anni '90, con risultati imprevedibili.
2 <html>L'elemento radice, che contiene tutti gli altri. L'attributo lang dichiara la lingua: serve ai lettori di schermo per la pronuncia, ai traduttori automatici, alla sillabazione.
3 <head>La «testa»: informazioni sul documento, che non compaiono nella pagina. Titolo, codifica, fogli di stile, script, descrizione.
4 <body>Il «corpo»: tutto il contenuto che il browser mostra.
5 <meta charset>La codifica dei caratteri. utf-8 copre tutte le lingue e gli emoji. Deve stare all'inizio della testa; senza, le lettere accentate possono diventare simboli strani come è.
6 <link>Collega una risorsa esterna. Con rel="stylesheet" è un foglio di stile CSS.
7 <script>Collega un file JavaScript. Con defer il browser lo scarica senza fermarsi e lo esegue quando la pagina è stata letta tutta.
HTML5 non obbliga a scrivere <html>, <head> e <body>: se mancano, il browser li crea da solo. In XHTML erano obbligatori, e quasi tutti gli sviluppatori continuano a scriverli, per chiarezza.
Dentro la testa
La testa contiene i metadati, cioè i dati sul documento. Gli elementi più usati:
| Elemento | Esempio | A cosa serve |
|---|---|---|
title | <title>Chi siamo — Pizzeria da Gino</title> | titolo della scheda, dei preferiti e dei risultati di ricerca. Obbligatorio |
meta charset | <meta charset="utf-8"> | codifica dei caratteri |
meta viewport | <meta name="viewport" content="width=device-width, initial-scale=1"> | indispensabile sui telefoni: senza, la pagina viene disegnata larga 980 pixel e rimpicciolita. Lo vedrai nel modulo sul design responsive |
meta description | <meta name="description" content="Pizza napoletana a Pisa dal 1978"> | il riassunto che i motori di ricerca mostrano sotto il titolo |
link rel="stylesheet" | <link rel="stylesheet" href="stile.css"> | foglio di stile esterno; con media="print" vale solo in stampa |
link rel="icon" | <link rel="icon" href="favicon.png"> | l'icona della scheda (favicon) |
script | <script src="app.js" defer></script> | codice JavaScript |
base | <base href="https://www.example.com/news/"> | l'indirizzo di partenza per tutti i link relativi della pagina: con questo, archives.html diventa https://www.example.com/news/archives.html. Da usare con cautela: vale per tutti i link |
Il markup semantico
Struttura da una parte, aspetto dall'altra
Negli ultimi vent'anni si è affermato un principio condiviso: l'HTML descrive solo la struttura e il significato del contenuto; come deve apparire lo decide il CSS. Scrivere HTML semantico significa scegliere ogni elemento per quello che il contenuto è, non per come apparirà: un titolo è h2 perché è un titolo di secondo livello, non perché lo vuoi grande e in grassetto.
Markup di presentazione
<font size="5" color="red"><b>Offerte</b></font> <br><br> <center>Solo per oggi!</center>
font e center sono stati eliminati dallo standard: descrivono l'aspetto, non il significato.
Markup semantico
<h2>Offerte</h2> <p class="avviso">Solo per oggi!</p>
Colore, dimensioni e centratura vanno nel CSS, una volta per tutto il sito.
Scrivere HTML semantico conviene per quattro motivi:
manutenzioneIl markup semantico è più facile da aggiornare: per cambiare il colore di tutti i titoli si modifica una regola CSS, non cento pagine.
velocitàLe pagine sono più veloci da scrivere e più leggere da scaricare: niente attributi di stile ripetuti ovunque.
accessibilitàChi usa un lettore di schermo naviga per titoli, liste e sezioni. Una pagina fatta solo di div è, per lui, un muro di testo indistinto.
motori di ricercaLa semantica dice ai motori di ricerca quali contenuti sono importanti: un h1 pesa più di un paragrafo qualunque (è la SEO, Search Engine Optimization).
Il testo
Titoli: da h1 a h6
L'HTML prevede sei livelli di titolo, da h1 a h6: più alto il numero, meno importante il titolo. I titoli sono lo strumento principale per mostrare ai lettori (e ai lettori di schermo, e ai motori di ricerca) la struttura del documento, come l'indice di un libro.
Ogni browser ha il suo stile predefinito per i titoli, facile da cambiare con il CSS. Proprio per questo il livello va scelto per il significato, mai per l'aspetto:
- non scegliere
h3perché vuoi un testo in grassetto da 16 punti: sceglih3perché è un titolo di terzo livello; - di solito c'è un solo
h1per pagina, il titolo principale; - non saltare livelli: dopo un
h2viene unh3, non unh5.
Paragrafi, a capo e separatori
<p>Il paragrafo, l'unità di base del testo. È un contenitore: può contenere testo ed elementi in linea, ma non altri blocchi come titoli, liste o altri paragrafi.
<br>Un a capo dentro lo stesso blocco. Adatto a indirizzi e poesie, dove l'a capo fa parte del contenuto; non per creare spazio, che è compito del CSS.
<hr>Un cambio di argomento tra paragrafi, come un cambio di scena in un racconto. Il browser lo disegna come una riga orizzontale. Non serve tra una section e l'altra: il cambio è già implicito.
<pre>Testo preformattato: il browser rispetta spazi e a capo così come sono, con un carattere a spaziatura fissa. Per codice, poesie visive, disegni in caratteri ASCII.
Il paragrafo va usato solo se non c'è un elemento più specifico. Queste due versioni sono entrambe valide, ma la seconda dice di più:
Corretto ma generico
<section> … <p>Ultima modifica: 2001-04-23</p> <p>Autore: fred@example.com</p> </section>
Meglio
<section> … <footer>Ultima modifica: 2001-04-23</footer> <address>Autore: fred@example.com</address> </section>
Citazioni
<blockquote>Una citazione lunga, presa da un'altra fonte, su un blocco a sé. L'attributo cite può indicare l'URL della fonte.
<q>Una citazione breve, dentro una frase. Il browser aggiunge da solo le virgolette, adatte alla lingua della pagina.
<cite>Il titolo di un'opera: un libro, un film, un articolo, una canzone. Il browser lo mostra in corsivo.
Gli elementi di testo in linea
Gli elementi in linea (inline) non interrompono il flusso del testo: stanno dentro una riga, senza andare a capo. HTML5 ne definisce più di trenta. Ecco quelli che userai di più, ognuno con il suo significato preciso.
| Elemento | Significato | Aspetto predefinito |
|---|---|---|
strong | importanza forte, serietà, urgenza: qualcosa che il lettore deve vedere prima del resto | grassetto |
em | enfasi: la parola su cui cade l'accento della frase, che ne cambia il senso | corsivo |
b | attirare l'attenzione senza dare importanza: parole chiave in un riassunto, nomi di prodotti in una recensione | grassetto |
i | una voce diversa dal testo normale: termini tecnici, parole straniere, nomi scientifici, pensieri, nomi di navi | corsivo |
mark | testo evidenziato perché rilevante in questo contesto, come i risultati di una ricerca | sfondo giallo |
small | note a margine, clausole in piccolo, avvisi legali | più piccolo |
s | informazioni non più valide | barrato |
abbr | abbreviazione o acronimo; con title si indica la forma estesa | a volte sottolineato a puntini |
dfn | il punto in cui un termine viene definito | corsivo |
time | una data o un'ora; con datetime in formato leggibile dalle macchine | nessuno |
code, kbd, samp, var | codice, tasti da premere, output di un programma, variabile | spaziatura fissa (var in corsivo) |
sub, sup | pedice e apice: H2O, 103 | più piccolo, abbassato o alzato |
ins, del | testo aggiunto o tolto in una revisione; datetime e cite indicano quando e perché | sottolineato / barrato |
span | nessun significato: un contenitore in linea generico, utile per applicare stili o attributi come lang | nessuno |
wbr | un punto in cui una parola lunghissima può andare a capo, se serve | invisibile |
Passa il mouse su GDO: il title dell'abbreviazione compare come suggerimento.
strong o b? em o i? La domanda da farsi è: «se lo leggessi ad alta voce, cambierei il tono?». Un avvertimento importante è strong; il nome di un prodotto in una recensione è b. «Non ho detto io che è stato lui» (l'accento cambia il senso) è em; smartphone come parola straniera è i.
Caratteri speciali: le entità
Alcuni caratteri non si possono scrivere direttamente: < e > hanno un significato riservato in HTML (aprono e chiudono i tag), altri sono difficili da digitare. Si scrivono con un'entità: &nome; oppure &#numero;.
| Entità | Numero | Risultato | Descrizione |
|---|---|---|---|
< | < | < | minore di: indispensabile per scrivere codice HTML in una pagina |
> | > | > | maggiore di |
& | & | & | la «e commerciale» stessa |
" | " | " | virgolette, dentro il valore di un attributo |
|   | (spazio) | spazio unificatore: non va a capo in quel punto, come in «10 km» |
© | © | © | copyright |
™ | ™ | ™ | marchio |
€ | € | € | euro |
è | è | è | lettera accentata (con UTF-8 si può scrivere direttamente) |
Nella seconda riga il <p> scritto senza entità viene preso per un tag vero: sparisce dal testo e il paragrafo si spezza in due.
Le liste
Liste puntate e numerate
L'HTML ha tre tipi di lista:
- non ordinata,
ul(unordered list): elementi in nessun ordine particolare, mostrati con un pallino; - ordinata,
ol(ordered list): elementi in un ordine preciso, numerati; - di descrizioni,
dl(description list): coppie di termine e descrizione.
In ul e ol ogni voce è un li (list item). Un li può contenere qualsiasi cosa, anche un'altra lista: così si creano le liste annidate.
La lista annidata sta dentro il li di «La mia soluzione», non tra un li e l'altro. Anche i menu di navigazione, nel codice, sono quasi sempre liste di link.
Numerazioni personalizzate
L'elemento ol ha tre attributi propri, e li uno:
| Attributo | Effetto |
|---|---|
reversed | numera al contrario, dal più alto al più basso (booleano) |
start="10" | il numero da cui partire |
type | 1 numeri (predefinito), a lettere minuscole, A maiuscole, i numeri romani minuscoli, I maiuscoli |
value (su li) | il numero di quella voce; le successive continuano da lì |
Liste di descrizioni
Una dl contiene gruppi di termini (dt) seguiti dalle loro descrizioni (dd). Va bene per glossari, domande e risposte, schede tecniche, metadati: qualsiasi elenco di coppie nome-valore. Un gruppo può avere più termini (sinonimi) o più descrizioni.
I link
L'elemento a
I collegamenti sono il cuore dell'ipertesto. Si creano con l'elemento a (da anchor, «àncora») e hanno due parti: la destinazione, nell'attributo href, e l'etichetta, il contenuto dell'elemento, su cui si clicca. L'etichetta può essere testo o anche un'immagine.
Gli attributi principali di a:
| Attributo | A cosa serve |
|---|---|
href | l'indirizzo della destinazione |
target | dove aprirla: _self (la scheda attuale, predefinito), _blank (una nuova scheda), _parent e _top (il contesto genitore o quello più esterno, quando la pagina è dentro un iframe), oppure il nome di un iframe |
download | scaricare il file invece di aprirlo; un valore, se c'è, è il nome da dare al file |
rel | la relazione tra la pagina e la destinazione, per esempio nofollow, noopener, noreferrer, external |
hreflang | la lingua della pagina di destinazione |
type | un'indicazione del tipo MIME della destinazione |
Aprire nuove schede con misura. target="_blank" toglie all'utente la scelta, e il tasto Indietro non funziona più. Usalo solo quando c'è un motivo, per esempio per non perdere un modulo a metà. Il testo del link deve dire dove porta: «scarica il programma del corso (PDF, 2 MB)», non «clicca qui».
Indirizzi assoluti e relativi
Per una risorsa su un altro sito serve un riferimento assoluto completo: il protocollo (https://), il nome di dominio, l'eventuale percorso e il nome del file. Per le risorse del tuo sito si usano quasi sempre riferimenti relativi, più brevi: se l'indirizzo non comincia con https://, il browser lo chiede allo stesso server da cui ha ricevuto la pagina, partendo dalla cartella in cui si trova la pagina stessa.
I percorsi sul Web seguono le convenzioni di Unix:
- la barra
/separa le cartelle tra loro e dal nome del file; ..indica la cartella «sopra» quella attuale;- un percorso che comincia con
/parte dalla radice del sito.
Scegli nello strumento la pagina in cui scrivi il link e il file da raggiungere: vedrai il percorso da scrivere e i passi per costruirlo.
| Caso | Regola | Esempio (sito qui sopra) |
|---|---|---|
| stessa cartella | solo il nome del file | da about.html a example.html: href="example.html" |
| cartella figlia | nome della cartella, barra, nome del file | da about.html a logo.gif: href="images/logo.gif" |
| cartella discendente | tutte le cartelle in ordine, separate da barre | da about.html a background.gif: href="css/images/background.gif" |
| cartella genitore o antenata | ../ per ogni livello da risalire | da members/index.html a about.html: href="../about.html"; da bio.html: href="../../about.html" |
| cartella «sorella» | risali con ../, poi scendi | da members/index.html a logo.gif: href="../images/logo.gif" |
| dalla radice | comincia con / | da bio.html a background.gif: href="/css/images/background.gif" |
| documento predefinito | il nome della cartella, senza file | da about.html a members/index.html: href="members/" |
Due trappole. I percorsi dalla radice (/about.html) funzionano solo quando il sito è pubblicato su un server: aprendo il file dal disco, / è la radice del tuo computer. E il documento predefinito (index.html per Apache e Nginx, default.html per IIS) viene servito quando chiedi una cartella: anche questo funziona solo su un server. Infine, sui server i nomi dei file distinguono maiuscole e minuscole: Logo.gif e logo.gif sono due file diversi.
Link dentro la pagina
Per saltare a un punto della stessa pagina basta dare un id all'elemento di destinazione e usare #id come indirizzo. Negli esempi più vecchi si trovano àncore fatte con <a id="…"> dentro i titoli; oggi si mette l'id direttamente sul titolo.
Gli id devono essere unici nella pagina. È così che funziona anche la barra laterale di questi appunti.
L'elemento link e l'attributo rel
Da non confondere con a: l'elemento link sta nella testa e collega il documento a risorse esterne che non si cliccano. L'attributo rel dice che tipo di relazione c'è.
<head> <link rel="stylesheet" href="tema.css"> <link rel="stylesheet" href="stampa.css" media="print"> <!-- solo quando si stampa --> <link rel="icon" href="favicon.png" sizes="32x32"> <link rel="alternate" href="https://www.esempio.it/en/" hreflang="en"> </head>
Gli elementi di struttura
div, span e gli elementi di HTML5
div (division) e span sono contenitori senza significato: div è un blocco, span sta in linea. Non hanno alcuna presentazione propria: servono a raggruppare contenuti per applicare uno stile o per uno script, di solito con un attributo class o id.
Prima di HTML5, i siti complessi erano pieni zeppi di div annidati in altri div (qualcuno parlava di «div-ite»), e per dar loro un senso si usavano nomi di classe come header, nav, footer. HTML5 ha trasformato quei nomi ricorrenti in veri elementi.
Prima: tutto div
<div id="header"> <div id="nav">…</div> </div> <div id="main"> <div class="post">…</div> </div> <div id="sidebar">…</div> <div id="footer">…</div>
HTML5: elementi semantici
<header> <nav>…</nav> </header> <main> <article>…</article> </main> <aside>…</aside> <footer>…</footer>
Ecco gli elementi di struttura introdotti da HTML5:
<header>L'intestazione: di solito logo, titolo, eventuale slogan, navigazione principale. Può stare in cima alla pagina, ma anche in cima a un article o a una section.
<footer>Il piè di pagina: materiale meno importante, come una versione ridotta della navigazione, il copyright, l'informativa sulla privacy, i link ai social. Anche questo vale per la pagina o per un singolo articolo.
<nav>Un blocco di navigazione principale: link ad altre pagine o ad altre parti della stessa. Non ogni gruppo di link è un nav: solo i sistemi di navigazione importanti.
<main>Il contenuto principale e unico del documento, escluso ciò che si ripete in tutte le pagine (navigazione, logo, footer). Uno solo per pagina (visibile).
<article>Un contenuto autonomo, che avrebbe senso anche letto da solo, fuori dalla pagina: un articolo di giornale, un post, un commento, la scheda di un prodotto.
<section>Una sezione tematica del documento, di solito con un titolo proprio: i capitoli di un articolo, le parti di una home page.
<aside>Un contenuto correlato solo di sfuggita a quello intorno: barre laterali, citazioni in evidenza, box di approfondimento, gruppi di pubblicità.
<figure>Un contenuto a sé stante (immagine, grafico, codice, poesia) con un'eventuale didascalia <figcaption>. Lo vedrai più avanti, con le immagini.
<details>Un blocco che si apre e si chiude con un clic, senza JavaScript. Il titolo sempre visibile è il suo <summary>.
Come per nav, il browser non applica alcuno stile particolare a questi elementi: si comportano come dei div. La differenza è tutta nel significato, che però serve a lettori di schermo, motori di ricerca e a chiunque legga il codice. Nell'esempio il CSS disegna un bordo con il nome di ogni elemento: osserva la struttura e apri l'albero DOM.
section, article o div?
La specifica avverte che section non è un contenitore generico: per quello c'è già div. Quando un elemento serve solo per lo stile o per comodità di uno script, si usa div. Un buon test: il contenuto merita di comparire nell'indice del documento? Se sì, è una section (e avrà un titolo); altrimenti, un div.
E tra article e section: chiediti se il contenuto avrebbe senso da solo, pubblicato altrove o condiviso. Un post del blog sì (article); il paragrafo «Metodi» di una relazione no (section).
details e summary
Un piccolo gioiello di HTML5: un blocco che si apre e si chiude con un clic, perfetto per le domande frequenti, senza una riga di JavaScript. L'attributo open lo fa partire aperto.
Contatti: address
L'elemento address rappresenta le informazioni di contatto dell'article o del body più vicino che lo contiene: se sta nel body, i contatti valgono per tutto il documento. Non va usato per un indirizzo postale qualsiasi, ma solo per i contatti di chi è responsabile del contenuto. Di solito sta in un footer.
Le immagini
L'elemento img
L'elemento img inserisce un'immagine nel punto in cui compare. È un elemento vuoto: ha solo attributi, niente contenuto né tag di chiusura.
| Attributo | A cosa serve |
|---|---|
src | l'URL dell'immagine. Obbligatorio |
alt | il testo alternativo: sostituisce l'immagine quando non si vede. Obbligatorio (vuoto solo per immagini decorative) |
width, height | le dimensioni in pixel, senza unità. Anche se poi il CSS le cambia, conviene indicarle: il browser riserva subito lo spazio e la pagina non «salta» mentre l'immagine arriva |
loading="lazy" | scarica l'immagine solo quando sta per entrare nello schermo: pagine lunghe molto più veloci |
srcset, sizes | versioni diverse della stessa immagine per schermi diversi (più avanti) |
usemap | collega l'immagine a una mappa di aree cliccabili (più avanti) |
L'ultima immagine non esiste: al suo posto il browser mostra il testo di alt (alcuni browser, come Safari, solo un'icona di immagine rotta se lo spazio è poco). È anche quello che legge un lettore di schermo, ed è ciò che «vede» un motore di ricerca.
Scrivere un buon alt
Il testo alternativo non è una descrizione tecnica dell'immagine, ma ciò che l'immagine comunica in quel contesto. La prova: se al posto dell'immagine leggessi il testo di alt, la pagina avrebbe ancora senso?
Da evitare
<img src="IMG_4032.jpg" alt="IMG_4032.jpg"> <img src="torre.jpg" alt="immagine"> <img src="logo.png"> <!-- alt mancante --> <img src="freccia.png" alt="freccia verde a destra">
Meglio
<img src="torre.jpg" alt="La Torre di Pisa al tramonto"> <img src="logo.png" alt="Pizzeria da Gino, torna alla home"> <img src="freccia.png" alt="Pagina successiva"> <img src="decoro.png" alt=""> <!-- solo decorativa -->
- un'immagine dentro un link descrive la destinazione: il logo che porta alla home dice «torna alla home»;
- non serve scrivere «immagine di…»: il lettore di schermo annuncia già che è un'immagine;
- le immagini puramente decorative hanno
alt=""(vuoto, ma presente): così il lettore di schermo le salta. Meglio ancora, se sono solo decorazione, metterle nel CSS come sfondo.
Formati: nel codice o nel CSS?
| Formato | Tipo | Adatto a | Note |
|---|---|---|---|
JPEG (.jpg) | raster, con perdita | fotografie | milioni di colori, file piccoli; niente trasparenza |
PNG (.png) | raster, senza perdita | grafica, schermate, testo, trasparenze | file più pesanti del JPEG per le foto |
GIF (.gif) | raster, 256 colori | piccole animazioni | formato storico, oggi sostituito da video brevi |
| WebP, AVIF | raster moderni | tutto | a parità di qualità pesano molto meno di JPEG e PNG; supportano trasparenza e animazione |
SVG (.svg) | vettoriale | loghi, icone, schemi, grafici | descritto da forme geometriche in XML: nitido a qualsiasi ingrandimento, spesso leggerissimo |
Un'immagine raster è una griglia di pixel: ingrandita, si sgrana. Un'immagine vettoriale è una descrizione di forme: il browser la ridisegna a qualsiasi dimensione. Tutte le illustrazioni degli esempi di questo corso sono SVG.
img è il modo più antico per mostrare un'immagine, ma non l'unico. Per le immagini puramente decorative, come sfondi sfumati, motivi, bordi ornamentali, ha senso tenerle fuori dal markup e metterle nel CSS con background-image. Quando invece l'immagine è contenuto, come le foto di una galleria o il prodotto in una scheda, img è la scelta semanticamente corretta.
figure e figcaption
L'elemento figure contiene un contenuto autonomo (un'immagine, uno schema, un blocco di codice, una poesia) a cui il testo fa riferimento come a un'unità, con una didascalia facoltativa figcaption, come prima o ultima cosa al suo interno. Il test: la figura si potrebbe spostare altrove nel documento (in fondo, in un'appendice) senza che il testo perda senso? Ma deve esserci: non è un abbellimento facoltativo.
Per questo figure non va usato per ogni immagine: non per il logo del sito, per i banner pubblicitari o per le decorazioni. Va usato quando il contenuto ha una didascalia ed è essenziale, ma la sua posizione esatta è poco importante.
Immagini responsive: srcset e picture
Un telefono con uno schermo largo 400 pixel non ha bisogno della stessa foto da 2.000 pixel che serve a un monitor grande: scaricarla spreca dati e tempo. Con srcset si offrono al browser più versioni della stessa immagine, ognuna con la sua larghezza reale (il descrittore w); con sizes si dice quanto sarà larga l'immagine nella pagina. Il browser fa i conti, tenendo conto anche della densità dello schermo, e scarica solo la versione adatta.
L'immagine dice quale versione è arrivata. Su uno schermo ad alta densità (come i Retina) il browser tende a scegliere la versione più grande; e una volta scaricata quella grande, di solito non torna indietro a quella piccola. Per vedere il cambio, parti dalla vista Telefono e ricarica la pagina.
srcset serve quando l'immagine è la stessa a risoluzioni diverse. Quando invece vuoi un'immagine diversa (un ritaglio più stretto sul telefono, un formato più moderno dove è supportato) si usa picture: contiene uno o più source con una condizione, e un img finale di riserva. Il browser usa il primo source che soddisfa la condizione.
Sullo schermo stretto vince il primo source. Su quello largo, i browser che conoscono il formato AVIF (quasi tutti, oggi) usano il secondo, più leggero; gli altri ricadono sull'img finale. È così che si offrono formati moderni senza lasciare indietro nessuno. L'alt si scrive una volta sola, sull'img.
Le mappe di immagini
Una mappa di immagine divide un'immagine in regioni e associa un'azione (di solito un link) a ciascuna. Serve un img con l'attributo usemap="#nome" e un elemento map con lo stesso name, che contiene un area per ogni regione.
Mercurio ha un raggio di soli 3 pixel: prova a centrarlo. È un buon esempio di un limite delle mappe: le aree troppo piccole sono difficili da usare, soprattutto con le dita.
| Attributo di area | Valori | Significato |
|---|---|---|
shape | rect, circle, poly, default | la forma della regione; default è tutto ciò che resta |
coords | numeri separati da virgole | rect: x e y dell'angolo in alto a sinistra, x e y di quello in basso a destra.circle: x e y del centro, raggio.poly: x1, y1, x2, y2, … xN, yN; il poligono si chiude da solo tornando al primo punto |
alt | testo | il testo alternativo della regione: obbligatorio se c'è href |
href, target, download | come per a | destinazione e modo di aprirla |
Le coordinate sono in pixel, con l'origine nell'angolo in alto a sinistra dell'immagine e la y che cresce verso il basso. Attenzione: le coordinate non si adattano se l'immagine viene ridimensionata con il CSS. Per questo oggi le mappe si usano poco, e si preferiscono SVG con link al loro interno o immagini sovrapposte a pulsanti.
Video, audio e pagine incorporate
Video, formati e sottotitoli
Prima di HTML5, per mostrare un video servivano plugin come Flash. Oggi basta l'elemento video, e il browser fornisce da solo i controlli per la riproduzione.
| Attributo | Effetto |
|---|---|
src | l'URL del video (oppure si usano elementi source) |
controls | mostra i controlli: riproduci, pausa, volume, schermo intero |
width, height | le dimensioni del riquadro |
poster | un'immagine da mostrare prima che il video parta |
autoplay | parte da solo. I browser lo permettono solo se il video è anche muted |
muted | audio disattivato |
loop | ricomincia ogni volta che finisce |
playsinline | sui telefoni resta nella pagina invece di aprirsi a schermo intero |
preload | auto (scarica tutto), metadata (solo durata e dimensioni), none (niente finché non si preme play) |
Non tutti i browser leggono gli stessi formati. Con più elementi source si offrono alternative: il browser usa il primo che sa riprodurre, grazie al tipo MIME in type. Il testo dentro video, dopo i source, compare solo nei browser che non supportano affatto l'elemento.
L'elemento track aggiunge sottotitoli o didascalie da un file di testo in formato WebVTT (.vtt): righe con un intervallo di tempo e il testo da mostrare. Sono fondamentali per chi non sente, e per chiunque guardi un video senza audio.
WEBVTT 00:00:00.000 --> 00:00:02.000 Questo è un video di prova. 00:00:02.000 --> 00:00:04.000 I sottotitoli arrivano da un file .vtt
L'elemento audio
audio funziona esattamente come video, senza immagine: stessi attributi (controls, autoplay, loop, muted, preload) e stessi source alternativi.
Rispetta chi legge. Un video o un audio che parte da solo con il suono è una delle cose più fastidiose del Web, e un problema serio per chi usa un lettore di schermo, che viene sovrastato. È per questo che i browser bloccano l'autoplay con audio. Un video di sfondo decorativo va sempre muted, e meglio se l'utente può fermarlo.
iframe
Un iframe (inline frame) incorpora un'altra pagina web dentro la pagina corrente: una mappa, un video di YouTube, un modulo di pagamento. È un contesto di navigazione annidato: una specie di browser nel browser, con il suo documento, la sua cronologia e i suoi script. Anche le anteprime degli esempi di questo corso sono iframe.
srcè l'indirizzo della pagina da incorporare;srcdoccontiene direttamente il codice HTML da mostrare (vince susrc);namedà un nome al contesto: un link contargetuguale a quel nome si aprirà dentro l'iframe;titledescrive il contenuto per i lettori di schermo: va sempre messo;sandboxlo chiude in una «scatola di sabbia»: senza valori, la pagina incorporata non può eseguire script, inviare moduli o aprire finestre. Si concedono i permessi uno alla volta, comeallow-scriptsoallow-forms.
Il target nei contesti annidati. Dentro un iframe, target="_parent" apre il link nella pagina che lo contiene e _top nella finestra più esterna di tutte. Per ragioni di sicurezza molti siti (banche, social) vietano di essere incorporati in un iframe altrui, con l'intestazione HTTP X-Frame-Options o Content-Security-Policy: così nessuno può mostrarli dentro una pagina ingannevole.
embed, object e param
Due elementi più antichi, nati per integrare contenuti esterni gestiti da un plugin o da un'applicazione esterna:
embedè un elemento vuoto:srcè l'indirizzo della risorsa etypeil suo tipo MIME, che decide quale programma usare;objectè più flessibile: a seconda della risorsa (indata, con il tipo intype) viene trattato come un'immagine, come un contesto annidato o come un plugin. Il suo contenuto è l'alternativa se la risorsa non si carica. I parametri per il plugin si passavano con elementiparam(connameevalueentrambi obbligatori), oggi considerati obsoleti.
Oggi i plugin non esistono più (Flash è stato dismesso nel 2020), e i due elementi si usano soprattutto per mostrare un PDF o un'immagine SVG.
Il PDF non esiste, quindi compare il contenuto alternativo con il link. Con un file vero, i browser da computer mostrerebbero il documento in un piccolo lettore.
Le tabelle
table, tr, th e td
Una tabella serve a presentare dati tabellari: informazioni che hanno senso in righe e colonne, come un orario, un listino, i risultati di un campionato. La tabella (table) è fatta di righe (tr, table row), e ogni riga di celle: td (table data) per i dati, th (table header) per le intestazioni.
Senza CSS una tabella non ha bordi. border-collapse: collapse unisce i bordi delle celle adiacenti in una riga sola.
Titolo, intestazione, corpo e piede
Una tabella completa si divide in parti con un significato preciso:
<caption>Il titolo della tabella. Va subito dopo <table>. Aiuta tutti, e soprattutto chi usa un lettore di schermo, a capire di che cosa parla.
<thead>Le righe di intestazione. Se la tabella viene stampata su più fogli, il browser le ripete in cima a ogni pagina.
<tbody>Il corpo con i dati. Se non lo scrivi, il browser lo aggiunge da solo.
<tfoot>Il piede: totali, medie, note.
scopeSu un th, dice se è l'intestazione di una colonna (col) o di una riga (row): i lettori di schermo lo usano per annunciare ogni cella con la sua intestazione.
Celle che si estendono: colspan e rowspan
Una cella può occupare più colonne con colspan="n" o più righe con rowspan="n". Le celle «coperte» non si scrivono: nelle righe successive a un rowspan, quella colonna è già occupata.
Nella riga delle 11 ci sono solo due celle scritte: la prima colonna di dati è occupata dal rowspan="2" della riga sopra, e «Ricevimento» copre le altre due.
Tabelle per impaginare: no
Negli anni '90 le tabelle si usavano per costruire l'impaginazione, con colonne e barre laterali fatte di celle. Il risultato era codice illeggibile, pagine inaccessibili ai lettori di schermo e impossibili da adattare ai telefoni.
I moduli
Il form e le etichette
Un modulo (form) raccoglie dati dall'utente e li invia a un server. Due attributi decidono dove e come, e si collegano direttamente a ciò che hai visto nel modulo su HTTP:
action: l'URL del programma sul server che riceverà i dati;method:get(i dati nell'URL, dopo il?) oppurepost(i dati nel corpo della richiesta).
Ogni campo da inviare deve avere un attributo name: i dati partono come coppie name=valore. Un campo senza name non viene inviato.
Ogni campo ha bisogno di un'etichetta che dica cosa inserire. L'elemento label la collega al campo in due modi: avvolgendolo, oppure con l'attributo for uguale all'id del campo. Il collegamento ha due effetti concreti: cliccare l'etichetta attiva il campo (comodissimo con caselle piccole) e i lettori di schermo leggono l'etichetta quando il campo riceve il fuoco.
Le prime due scritte attivano il campo; la terza no. Il placeholder (il testo grigio dentro il campo) non sostituisce l'etichetta: sparisce appena si scrive.
I tipi di input
L'elemento input cambia completamente comportamento a seconda del suo type. I tipi introdotti da HTML5 portano con sé la validazione e, sui telefoni, la tastiera giusta: numerica per tel e number, con la chiocciola per email.
I radio con lo stesso name formano un gruppo: se ne può scegliere uno solo. Premi Invia per vedere quali coppie nome=valore partirebbero.
textarea, select e datalist
<textarea>Testo su più righe. Non è vuoto come input: il testo iniziale va tra i tag. rows e cols ne danno le dimensioni.
<select>Un menu a tendina con le sue option, raggruppabili con optgroup. Con multiple diventa un elenco a scelta multipla.
<datalist>Suggerimenti per un campo di testo, collegato con l'attributo list: l'utente può sceglierne uno o scrivere altro.
<button>Un pulsante. type="submit" (predefinito dentro un form) invia, type="reset" svuota i campi, type="button" non fa nulla da solo (serve JavaScript).
<fieldset>Raggruppa campi correlati, con un titolo in legend. Indispensabile per i gruppi di radio e checkbox.
<output>, <progress>, <meter>Il risultato di un calcolo, l'avanzamento di un'operazione, una misura in un intervallo noto (come lo spazio occupato su un disco).
La validazione
Il browser può controllare i dati prima di inviarli, e mostrare un messaggio accanto al campo sbagliato, grazie ad alcuni attributi:
| Attributo | Controllo |
|---|---|
required | il campo non può restare vuoto |
minlength, maxlength | lunghezza minima e massima del testo |
min, max, step | limiti e passo per numeri e date |
pattern | il valore deve corrispondere a un'espressione regolare, come [0-9]{5} per un CAP |
type | email e url controllano già il formato |
novalidate (su form) | disattiva tutti i controlli |
Il CSS colora i bordi in base alla validità con le pseudo-classi :user-valid e :user-invalid, che scattano solo dopo che l'utente ha toccato il campo (:valid e :invalid valgono invece da subito). Ricorda: la validazione nel browser è solo una comodità per l'utente. Chiunque può aggirarla, quindi il server deve sempre ricontrollare tutto.
Altri attributi utili: placeholder (un esempio dentro il campo, che non sostituisce l'etichetta), value (il valore iniziale), disabled (campo spento e non inviato), readonly (non modificabile ma inviato), autocomplete (aiuta il browser a riempire nome, email, indirizzo, password), autofocus (il cursore parte lì), inputmode (la tastiera da mostrare sul telefono).
Gli attributi globali
Attributi che valgono ovunque
Alcuni attributi si possono usare su qualsiasi elemento:
| Attributo | A cosa serve |
|---|---|
id | un nome unico nella pagina: per le àncore, per label for, per CSS e JavaScript |
class | uno o più nomi di classe separati da spazi, riutilizzabili: il gancio principale per il CSS |
style | regole CSS direttamente sull'elemento. Da usare il meno possibile |
title | informazioni aggiuntive, mostrate come suggerimento al passaggio del mouse. Non accessibile da tastiera o touch: non metterci informazioni essenziali |
lang | la lingua del contenuto, come lang="en" per una citazione in inglese |
dir | la direzione del testo: ltr (sinistra-destra) o rtl (destra-sinistra, per arabo ed ebraico) |
hidden | nasconde l'elemento, come se non ci fosse |
tabindex | rende un elemento raggiungibile con il tasto Tab (0) o solo via script (-1). Valori positivi sconsigliati: stravolgono l'ordine naturale |
contenteditable | rende il contenuto modificabile direttamente nella pagina |
data-* | attributi personalizzati per conservare dati, come data-prezzo="9.90": leggibili da CSS e JavaScript |
draggable, translate, spellcheck | trascinabile, da non tradurre automaticamente, controllo ortografico |
Il CSS legge l'attributo data-valuta con attr() e lo aggiunge dopo il prezzo.
id o class?
id
Uno solo per pagina con quel valore, e un elemento ha un solo id. Identifica un elemento preciso: la destinazione di un'àncora, il campo collegato a una label.
<section id="contatti">…</section>
class
Quanti elementi vuoi con la stessa classe, e ogni elemento può averne più d'una. Descrive un «tipo» di elemento a cui applicare lo stesso stile.
<p class="avviso importante">…</p>
Accessibilità e validazione
Un Web per tutti
Una pagina è accessibile quando può essere usata da chiunque: da chi non vede e usa un lettore di schermo che legge la pagina ad alta voce, da chi non può usare il mouse e naviga con la tastiera, da chi vede male e ingrandisce il testo, da chi non sente, da chi ha difficoltà cognitive. Ma anche da chi ha un braccio ingessato, usa il telefono sotto il sole o ha una connessione lenta.
Le regole internazionali sono le WCAG (Web Content Accessibility Guidelines) del W3C. In Europa l'European Accessibility Act le rende obbligatorie dal giugno 2025 per molti servizi privati, come e-commerce e banche; in Italia la Legge Stanca le impone da anni ai siti pubblici.
Le regole d'oro:
- Usa l'elemento giusto. Un pulsante è un
button, non undivcliccabile: ilbuttonsi raggiunge con Tab, si attiva con Invio e viene annunciato come pulsante, gratis. - Struttura con i titoli, in ordine, senza saltare livelli: molti utenti di lettori di schermo navigano saltando da un titolo all'altro.
- Usa i punti di riferimento:
header,nav,main,footerpermettono di saltare direttamente al contenuto. - Dai un
alta ogni immagine, vuoto se decorativa. - Collega ogni campo alla sua
label. - Link con testi chiari: «programma del corso (PDF)», non «clicca qui». Chi usa un lettore di schermo spesso ascolta l'elenco dei soli link.
- Dichiara la lingua con
lang, anche per le frasi in un'altra lingua. - Contrasto sufficiente tra testo e sfondo, e mai informazioni affidate solo al colore («i campi in rosso sono obbligatori»).
- Tutto deve funzionare da tastiera, e il fuoco deve essere visibile.
- Sottotitoli per i video, trascrizioni per gli audio.
Un finto pulsante
<div class="bottone" onclick="invia()"> Invia </div>
Non si raggiunge con Tab, non si attiva con Invio, il lettore di schermo lo legge come testo qualunque.
Un pulsante vero
<button type="button" class="bottone" onclick="invia()"> Invia </button>
Tastiera, fuoco e ruolo arrivano gratis. Lo stile si cambia con il CSS.
Quando l'HTML non basta (per esempio in componenti complessi costruiti con JavaScript) si possono aggiungere attributi ARIA (Accessible Rich Internet Applications), che descrivono ruoli e stati ai lettori di schermo: aria-label dà un nome a un pulsante che contiene solo un'icona, aria-expanded dice se un menu è aperto. La prima regola di ARIA però è: se esiste un elemento HTML che fa già quella cosa, usa quello.
<button type="button" aria-label="Chiudi">✕</button> <nav aria-label="Percorso">Home › Corsi › Progettazione Web</nav>
Il validatore e gli errori tipici
Il browser è molto tollerante: corregge in silenzio moltissimi errori, e una pagina sbagliata spesso «sembra» funzionare. Ma ogni browser potrebbe correggerla in modo diverso, e i problemi emergono dopo, con il CSS o con un lettore di schermo. Per questo si passa il codice al validatore del W3C (validator.w3.org), che accetta un indirizzo, un file o codice incollato. Gli errori più comuni che segnala:
- tag non chiusi o annidati male;
idripetuti nella stessa pagina;- immagini senza
alt; - elementi in posti dove non possono stare, come un
divdentro unp, o unlifuori da una lista; - attributi inesistenti o scritti male;
- la
&non codificata negli URL (va scritta&dentrohref, anche se i browser perdonano).
Un p non può contenere un div: il browser chiude il paragrafo prima del div, e il </p> finale diventa un nuovo paragrafo vuoto. I li senza chiusura invece sono validi: il loro tag di chiusura è facoltativo.