HTML5 - struttura del documento, elementi semantici e form
In questa pagina 10
HTML (HyperText Markup Language) è il linguaggio con cui si scrive la struttura di una pagina web. La specifica ufficiale è l'HTML Living Standard del WHATWG, aggiornato di continuo (HTML5 è il nome storico della versione che ne ha fissato le basi nel 2014). Si legge insieme a Linguaggi di markup - SGML, HTML e XMLUn linguaggio di markup aggiunge al testo marcatori che ne descrivono la struttura. SGML (ISO 8879, 1986) è il metalinguaggio da cui derivano HTML fino alla 4.01 e XML 1.0 (W3C, 1998, un sottoinsieme semplificato); HTML5 ha un proprio algoritmo di parsing, tollerante, e non è né SGML né XML. Un documento XML è ben formato se rispetta la sintassi (un'unica radice, tag annidati e chiusi, attributi tra virgolette, nomi con maiuscole e minuscole distinte, entità per i caratteri speciali) ed è valido se in più rispetta uno schema. La DTD dichiara elementi (ELEMENT: EMPTY, ANY, #PCDATA, sequenza con la virgola, scelta con |, cardinalità ? * +) e attributi (ATTLIST: CDATA, ID, IDREF, enumerazioni; #REQUIRED, #IMPLIED, #FIXED); non ha tipi di dato e non conosce i namespace. XML Schema (XSD) è scritto in XML e ha tipi (xs:date, xs:positiveInteger), restrizioni con pattern, minOccurs e maxOccurs, key e keyref. I namespace (xmlns, xmlns:prefisso) identificano il vocabolario con un URI; gli attributi senza prefisso non appartengono a nessun namespace. XML è rigido e adatto a documenti e configurazioni (web.xml, pom.xml), HTML è tollerante e ha un vocabolario fisso; JSON è l'alternativa più compatta per scambiare dati e non ha attributi, schema standard o contenuto misto.Linguaggi di markup - SGML, HTML e XML → (da dove viene e come si confronta con XML) e prepara CSS3 - selettori, cascata, box model e layoutCSS descrive la presentazione: regole selettore { proprietà: valore }. Selettori: tipo, classe (.a), id (#a), attributo ([type="date"]), universale, combinatori (spazio discendente, > figlio, + fratello adiacente, ~ fratelli seguenti), pseudo-classi (:hover, :focus-visible, :nth-child, :not, :checked) e pseudo-elementi (::before, ::after). Cascata: tra più regole che toccano la stessa proprietà vince, nell'ordine, l'importanza (!important vince, e lo stile inline batte gli stili normali), poi la specificità (a,b,c) = (id, classi+attributi+pseudo-classi, tipi+pseudo-elementi) confrontata come numeri uno alla volta da sinistra, infine l'ordine di comparsa (l'ultima vince). Ereditarietà: color, font, line-height, text-align passano ai figli; margin, padding, border, background, width no; inherit, initial, unset la controllano. Box model: content, padding, border, margin; con content-box width è solo il contenuto, con border-box include padding e bordo; i margini verticali adiacenti collassano nel maggiore. display: block, inline, inline-block, none, flex, grid. position: static, relative, absolute (rispetto all'antenato posizionato), fixed, sticky. Flexbox è per una dimensione (justify-content, align-items, gap, flex-grow, flex-wrap), grid per due (grid-template-columns, fr, repeat, minmax, gap). Responsive: meta viewport, unità relative (rem, %, fr), media query @media (min-width), approccio mobile-first.CSS3 - selettori, cascata, box model e layout → e JavaScript - linguaggio, DOM ed eventiJavaScript (standard ECMAScript, Ecma-262) è il linguaggio dei browser: tipizzato dinamicamente, con sette tipi primitivi (number, string, boolean, undefined, null, bigint, symbol) e gli oggetti (anche array e funzioni); typeof null vale "object" per un errore storico; == converte i tipi, === no (si usa sempre ===); valori falsy: false, 0, 0n, "", null, undefined, NaN. let e const hanno visibilità di blocco e una zona morta prima della dichiarazione, var visibilità di funzione e hoisting; const impedisce di riassegnare il nome, non di modificare l'oggetto. Funzioni: dichiarazione (hoisted), espressione, arrow function (this lessicale), parametri predefiniti, rest e spread, destructuring. Array: map, filter, reduce, find, some, every, sort (senza comparatore ordina come stringhe). Closure: una funzione ricorda le variabili dell'ambiente in cui è nata. Eventi: addEventListener; propagazione in tre fasi (cattura, target, bolla), stopPropagation, preventDefault, delegazione con event.target e closest. DOM: albero di nodi; querySelector, createElement, append, replaceChildren, textContent (sicuro) contro innerHTML (rischio di XSS), classList, dataset. Moduli ES (type="module", import e export) sono differiti e in modalità strict. Event loop: un solo thread, call stack, coda dei task (setTimeout, eventi) e coda dei microtask (promise, await) svuotata dopo ogni task: l'esecuzione asincrona (fetch, async e await, Promise.all) è alla base di AJAX e il codice lungo blocca la pagina.JavaScript - linguaggio, DOM ed eventi →. Tutti gli esempi sono pezzi della pagina di prenotazione delle aule (Architettura delle applicazioni web - browser, server web e livelliUn'applicazione web è distribuita su più livelli (tier): presentazione (browser: HTML, CSS, JavaScript), logica applicativa (server web e application server) e dati (DBMS). Il client invia richieste HTTP, il server risponde; HTTP è senza stato, quindi lo stato dell'utente viaggia in cookie e sessioni. Il web server serve file statici, l'application server (container, per esempio Tomcat per le servlet Java) esegue codice che genera risposte dinamiche; spesso il web server fa da reverse proxy davanti all'application server. Il browser trasforma i byte della risposta in una pagina: decodifica, tokenizzazione e costruzione del DOM, CSS che diventa CSSOM, render tree, layout (reflow), paint e composizione; un script senza defer o async blocca il parsing, il CSS blocca il rendering. Origine = schema + host + porta; la same-origin policy limita ciò che uno script può leggere da altre origini. Web 1.0: pagine generate dal server, ogni azione ricarica la pagina; Web 2.0: AJAX, contenuti degli utenti, servizi REST; Web 3.0: dati con significato esplicito (RDF, linked data).Architettura delle applicazioni web - browser, server web e livelli →).
Struttura di un documento
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Prenotazione aule - Dipartimento</title>
<link rel="stylesheet" href="stile.css">
<script src="app.js" defer></script>
</head>
<body>
...contenuto visibile...
</body>
</html>Riga per riga:
<!DOCTYPE html>dice al browser di usare la modalità standard (senza, scatta la "quirks mode", che imita i vecchi browser e cambia vari dettagli del layout). Non è un tag ma una dichiarazione.<html lang="it">: l'elemento radice.langdichiara la lingua: serve ai lettori di schermo (pronuncia), ai correttori ortografici e ai motori di ricerca.<head>: metadati, non visibili.<meta charset="UTF-8">dichiara la codifica (deve stare nei primi 1024 byte e va anche inContent-Type: text/html; charset=utf-8, Caching, autenticazione, tipi MIME e URI in HTTPLa cache HTTP riusa le risposte senza contattare il server finche' sono fresche (Cache-Control: max-age, Expires; in mancanza una durata euristica pari a circa il 10% del tempo trascorso da Last-Modified) e, quando sono scadute, le rivalida con una richiesta condizionale (If-None-Match con ETag, If-Modified-Since con Last-Modified) alla quale il server risponde 304 senza corpo; no-store vieta di memorizzare, no-cache obbliga a rivalidare, private esclude le cache condivise. L'autenticazione usa 401 con WWW-Authenticate e la risposta Authorization: Basic (base64 di utente:password, solo sopra TLS) o Digest (hash con nonce); 407 vale per i proxy. Content-Type porta il tipo MIME (tipo/sottotipo; parametri come charset e boundary), Accept e gli altri header Accept-* guidano la negoziazione. Un URI (RFC 3986) e' scheme://userinfo@host:porta/percorso?query#frammento, con percent-encoding %HH per i byte non ammessi e regole per risolvere i riferimenti relativi.Caching, autenticazione, tipi MIME e URI in HTTP →).<meta name="viewport" ...>dice ai telefoni di usare la larghezza reale dello schermo e non una finestra virtuale di 980 pixel: senza, il responsive non funziona.<title>è il titolo della scheda e il testo dei risultati di ricerca.<link rel="stylesheet" href="stile.css">carica un foglio di stile;<script src="app.js" defer>carica uno script che viene eseguito dopo il parsing (Architettura delle applicazioni web - browser, server web e livelliUn'applicazione web è distribuita su più livelli (tier): presentazione (browser: HTML, CSS, JavaScript), logica applicativa (server web e application server) e dati (DBMS). Il client invia richieste HTTP, il server risponde; HTTP è senza stato, quindi lo stato dell'utente viaggia in cookie e sessioni. Il web server serve file statici, l'application server (container, per esempio Tomcat per le servlet Java) esegue codice che genera risposte dinamiche; spesso il web server fa da reverse proxy davanti all'application server. Il browser trasforma i byte della risposta in una pagina: decodifica, tokenizzazione e costruzione del DOM, CSS che diventa CSSOM, render tree, layout (reflow), paint e composizione; un script senza defer o async blocca il parsing, il CSS blocca il rendering. Origine = schema + host + porta; la same-origin policy limita ciò che uno script può leggere da altre origini. Web 1.0: pagine generate dal server, ogni azione ricarica la pagina; Web 2.0: AJAX, contenuti degli utenti, servizi REST; Web 3.0: dati con significato esplicito (RDF, linked data).Architettura delle applicazioni web - browser, server web e livelli →).<body>: tutto ciò che si vede.
Sintassi
- Un elemento è tag di apertura, contenuto, tag di chiusura:
<p>Testo</p>. Gli elementi vuoti (void) non hanno contenuto né chiusura:<br>,<hr>,<img>,<input>,<meta>,<link>. La barra finale (<br/>) è ammessa e ignorata. - Gli attributi stanno nel tag di apertura:
nome="valore". Le virgolette sono facoltative se il valore è una parola senza spazi (type=text), ma conviene metterle sempre. Gli attributi booleani si scrivono senza valore:required,disabled,checked,hidden. - Nomi di tag e di attributi sono indifferenti alle maiuscole; si scrive in minuscolo.
- Le entità servono per i caratteri riservati:
<>&", e (spazio non separabile). I commenti sono<!-- ... -->. - Gli spazi e i ritorni a capo multipli nel testo si riducono a uno nella visualizzazione.
Il parser corregge
A differenza di XML, un errore non ferma il parser: ne decide la correzione (WHATWG HTML, algoritmo di parsing). Esempi, verificati in un browser ricostruendo il DOM da una stringa:
| sorgente | DOM costruito |
|---|---|
<table><tr><td>x</td></tr></table> |
aggiunge <tbody> fra table e tr |
<p>uno<p>due |
due paragrafi: il secondo <p> chiude il primo |
<p>testo<div>blocco</div> |
il <p> si chiude prima del <div> (un paragrafo non può contenere blocchi) |
<ul><li>A<li>B</ul> |
ogni <li> chiude il precedente |
<input required disabled> |
gli attributi booleani vengono riscritti required="" |
Conseguenza: il DOM che JavaScript vede può differire dal sorgente (nel caso <tbody>, un selettore table > tr non troverà nulla). Per evitare sorprese si scrive HTML con tag chiusi e annidati correttamente; esistono validatori (per esempio quello del W3C) che confrontano la pagina con la specifica.
Testo e elementi di base
| elemento | uso |
|---|---|
h1 ... h6 |
titoli, gerarchia: un h1 per pagina, poi h2, h3 senza saltare livelli |
p |
paragrafo |
ul, ol, li |
elenco puntato / numerato; dl, dt, dd elenco di definizioni |
strong, em |
importanza forte / enfasi (significato); b, i solo aspetto |
code, pre |
codice in riga / blocco che conserva spazi e a capo |
blockquote, q |
citazione in blocco / in riga |
br, hr |
a capo / interruzione tematica |
span, div |
contenitori senza significato in riga / a blocco |
Gli elementi si dividono (concetto di content model) in a blocco (iniziano su una riga nuova: p, div, ul, h1...) e in riga (inline: a, strong, span, img...). È una distinzione di default, che CSS può cambiare (CSS3 - selettori, cascata, box model e layoutCSS descrive la presentazione: regole selettore { proprietà: valore }. Selettori: tipo, classe (.a), id (#a), attributo ([type="date"]), universale, combinatori (spazio discendente, > figlio, + fratello adiacente, ~ fratelli seguenti), pseudo-classi (:hover, :focus-visible, :nth-child, :not, :checked) e pseudo-elementi (::before, ::after). Cascata: tra più regole che toccano la stessa proprietà vince, nell'ordine, l'importanza (!important vince, e lo stile inline batte gli stili normali), poi la specificità (a,b,c) = (id, classi+attributi+pseudo-classi, tipi+pseudo-elementi) confrontata come numeri uno alla volta da sinistra, infine l'ordine di comparsa (l'ultima vince). Ereditarietà: color, font, line-height, text-align passano ai figli; margin, padding, border, background, width no; inherit, initial, unset la controllano. Box model: content, padding, border, margin; con content-box width è solo il contenuto, con border-box include padding e bordo; i margini verticali adiacenti collassano nel maggiore. display: block, inline, inline-block, none, flex, grid. position: static, relative, absolute (rispetto all'antenato posizionato), fixed, sticky. Flexbox è per una dimensione (justify-content, align-items, gap, flex-grow, flex-wrap), grid per due (grid-template-columns, fr, repeat, minmax, gap). Responsive: meta viewport, unità relative (rem, %, fr), media query @media (min-width), approccio mobile-first.CSS3 - selettori, cascata, box model e layout →), mentre le regole su che cosa può contenere cosa (un p non contiene un div) restano.
Elementi semantici
Fino a HTML4 la struttura di una pagina si costruiva con <div id="header">, <div id="nav">: per il browser e per un lettore di schermo erano tutti uguali. HTML5 introduce elementi che dicono il ruolo del contenuto:
| elemento | ruolo |
|---|---|
header |
introduzione della pagina o di una sezione (logo, titolo) |
nav |
blocco di collegamenti di navigazione |
main |
il contenuto principale; uno solo per pagina |
section |
sezione tematica, di norma con un titolo |
article |
contenuto autonomo che avrebbe senso da solo (un articolo, un commento) |
aside |
contenuto collaterale (box laterale) |
footer |
piè di pagina o di sezione |
figure, figcaption |
figura con didascalia |
time |
data o ora, con datetime leggibile dalle macchine |
I vantaggi sono concreti: i lettori di schermo permettono di saltare a main o nav (si chiamano punti di riferimento, landmark), i motori di ricerca capiscono meglio la pagina e il CSS ha selettori significativi. Regola: usare div e span solo quando non c'è un elemento con il significato giusto.
Link, immagini e risorse
<a href="/aiuto.html">Aiuto</a> <!-- relativo alla radice del sito -->
<a href="https://aule.example.org/api/aule">Elenco aule</a> <!-- assoluto -->
<a href="#nuova">Vai al modulo</a> <!-- frammento: l'elemento con id="nuova" -->
<a href="mailto:aule@example.org">Scrivici</a>
<a href="https://altro.example.org" target="_blank" rel="noopener">Altro sito</a>
<img src="aula-a1.jpg" alt="Aula A1 vista dal fondo" width="640" height="360">- Un
hrefpuò essere un URI assoluto o relativo (risolto rispetto all'indirizzo della pagina: Caching, autenticazione, tipi MIME e URI in HTTPLa cache HTTP riusa le risposte senza contattare il server finche' sono fresche (Cache-Control: max-age, Expires; in mancanza una durata euristica pari a circa il 10% del tempo trascorso da Last-Modified) e, quando sono scadute, le rivalida con una richiesta condizionale (If-None-Match con ETag, If-Modified-Since con Last-Modified) alla quale il server risponde 304 senza corpo; no-store vieta di memorizzare, no-cache obbliga a rivalidare, private esclude le cache condivise. L'autenticazione usa 401 con WWW-Authenticate e la risposta Authorization: Basic (base64 di utente:password, solo sopra TLS) o Digest (hash con nonce); 407 vale per i proxy. Content-Type porta il tipo MIME (tipo/sottotipo; parametri come charset e boundary), Accept e gli altri header Accept-* guidano la negoziazione. Un URI (RFC 3986) e' scheme://userinfo@host:porta/percorso?query#frammento, con percent-encoding %HH per i byte non ammessi e regole per risolvere i riferimenti relativi.Caching, autenticazione, tipi MIME e URI in HTTP →);#idsalta a un elemento della stessa pagina. target="_blank"apre una nuova scheda;rel="noopener"impedisce alla nuova pagina di controllare quella di partenza.<img>richiedealt: il testo alternativo che il lettore di schermo legge e che compare se l'immagine non carica. Un'immagine decorativa haalt=""(vuoto, non assente).widtheheightriservano lo spazio e evitano che il layout "salti" quando arriva l'immagine.
Tabelle
Le tabelle servono per dati tabulari, non per impaginare (per quello c'è CSS). Le prenotazioni del 19 ottobre:
<table>
<caption>Aule prenotate nel giorno scelto</caption>
<thead>
<tr><th scope="col">Aula</th><th scope="col">Dalle</th><th scope="col">Alle</th><th scope="col">Studente</th></tr>
</thead>
<tbody>
<tr><th scope="row">Aula A1</th><td>09:00</td><td>11:00</td><td>Rossi</td></tr>
<tr><th scope="row">Aula A1</th><td>14:00</td><td>16:00</td><td>Bianchi</td></tr>
</tbody>
</table>captionè il titolo della tabella;thead,tbody,tfootraggruppano intestazione, corpo e piede;trè una riga;thuna cella di intestazione,tduna cella di dati.scopedice a che cosa si riferisce unath:col(la colonna sotto) orow(la riga a destra); i lettori di schermo leggono "Studente: Rossi" invece di una sequenza di valori.colspan="2"erowspan="2"fondono celle in orizzontale e in verticale. Una riga di totali che occupa tre colonne:<td colspan="3">Totale</td>.
Form
Un form raccoglie dati dall'utente e li invia al server. Il modulo di prenotazione:
<form action="/prenotazioni" method="post">
<fieldset>
<legend>Dati della prenotazione</legend>
<p>
<label for="aula_id">Aula</label>
<select id="aula_id" name="aula_id" required>
<option value="">Scegli...</option>
<option value="1">Aula A1 (80 posti)</option>
<option value="2">Aula B2 (45 posti)</option>
<option value="3">Lab Info (30 posti)</option>
</select>
</p>
<p>
<label for="giorno">Giorno</label>
<input type="date" id="giorno" name="giorno" required>
</p>
<p>
<label for="ora_inizio">Dalle</label>
<input type="time" id="ora_inizio" name="ora_inizio" required>
<label for="ora_fine">alle</label>
<input type="time" id="ora_fine" name="ora_fine" required>
</p>
<p>
<label for="studente">Cognome</label>
<input type="text" id="studente" name="studente" required minlength="2" maxlength="40">
</p>
</fieldset>
<button type="submit">Prenota</button>
</form>actionè l'indirizzo a cui si invia (predefinito: la pagina stessa);methodèget(predefinito) opost.label for="x"collega l'etichetta al campo conid="x": cliccando sull'etichetta si seleziona il campo e il lettore di schermo la legge. Un campo senzalabelè inaccessibile;placeholdernon la sostituisce.nameè il nome con cui il valore viaggia verso il server: un campo senzanamenon viene inviato.idserve perlabel, CSS e JavaScript. Qui inamesono i nomi delle colonne diprenotazione.fieldsetelegendraggruppano campi collegati.- Il pulsante
<button type="submit">invia;type="button"non fa nulla da solo (serve JavaScript);type="reset"ripristina i valori.
Tipi di input
type |
campo | note |
|---|---|---|
text (predefinito), search |
testo su una riga | |
email, url, tel |
testo con controllo di formato (email, url); tastiera adatta | tel non controlla nulla |
password |
testo nascosto | |
number |
numero | min, max, step |
date, time, datetime-local |
selettori nativi | il valore inviato è AAAA-MM-GG, HH:MM: coincide con le colonne SQL DATE e TIME |
checkbox |
casella | inviato solo se spuntata (valore on se manca value) |
radio |
scelta unica fra quelli con lo stesso name |
|
hidden |
non visibile | per passare un dato fisso |
file |
upload | richiede enctype="multipart/form-data" |
submit, button, reset |
pulsanti |
Altri controlli: <select> con <option> (il value è ciò che viaggia, il testo è ciò che si vede), <textarea> per testo su più righe, <button>. L'elemento <datalist> suggerisce valori a un input di testo.
GET e POST
method decide dove vanno i campi:
- GET: nell'URI, dopo il
?, comenome=valoreseparati da&(query string). Il browser, inviando un form congiorno=2026-10-19,studente=Dall'Olio Annae una casellasolo_liberespuntata, richiede:
GET /prenotazioni?giorno=2026-10-19&studente=Dall%27Olio+Anna&solo_libere=on HTTP/1.1 I valori sono codificati: spazio diventa +, l'apostrofo %27 (percent-encoding, Caching, autenticazione, tipi MIME e URI in HTTPLa cache HTTP riusa le risposte senza contattare il server finche' sono fresche (Cache-Control: max-age, Expires; in mancanza una durata euristica pari a circa il 10% del tempo trascorso da Last-Modified) e, quando sono scadute, le rivalida con una richiesta condizionale (If-None-Match con ETag, If-Modified-Since con Last-Modified) alla quale il server risponde 304 senza corpo; no-store vieta di memorizzare, no-cache obbliga a rivalidare, private esclude le cache condivise. L'autenticazione usa 401 con WWW-Authenticate e la risposta Authorization: Basic (base64 di utente:password, solo sopra TLS) o Digest (hash con nonce); 407 vale per i proxy. Content-Type porta il tipo MIME (tipo/sottotipo; parametri come charset e boundary), Accept e gli altri header Accept-* guidano la negoziazione. Un URI (RFC 3986) e' scheme://userinfo@host:porta/percorso?query#frammento, con percent-encoding %HH per i byte non ammessi e regole per risolvere i riferimenti relativi.Caching, autenticazione, tipi MIME e URI in HTTP →). GET è sicuro e idempotente: non deve modificare nulla (RFC 9110); la richiesta si può mettere nei segnalibri, condividere, mettere in cache; i dati restano visibili in cronologia e nei log, quindi mai password.
- POST: nel corpo del messaggio. Il modulo di prenotazione compilato con "Dall'Olio & Rossi" invia (catturato da un server di prova):
POST /prenotazioni HTTP/1.1
Content-Type: application/x-www-form-urlencoded
aula_id=1&giorno=2026-10-19&ora_inizio=09%3A00&ora_fine=11%3A00&studente=Dall%27Olio+%26+Rossi Nell'URI non compare nulla; non è idempotente: ripetere la richiesta può creare una seconda prenotazione (per questo il browser chiede conferma prima di rinviare). Si usa per operazioni che modificano lo stato. Si noti %3A per i due punti e %26 per la & che fa parte del valore: senza codifica sarebbe stata un separatore.
Il formato del corpo dipende da enctype: application/x-www-form-urlencoded (predefinito), multipart/form-data (obbligatorio con i file: ogni campo è una parte separata da un boundary, come descritto in Caching, autenticazione, tipi MIME e URI in HTTPLa cache HTTP riusa le risposte senza contattare il server finche' sono fresche (Cache-Control: max-age, Expires; in mancanza una durata euristica pari a circa il 10% del tempo trascorso da Last-Modified) e, quando sono scadute, le rivalida con una richiesta condizionale (If-None-Match con ETag, If-Modified-Since con Last-Modified) alla quale il server risponde 304 senza corpo; no-store vieta di memorizzare, no-cache obbliga a rivalidare, private esclude le cache condivise. L'autenticazione usa 401 con WWW-Authenticate e la risposta Authorization: Basic (base64 di utente:password, solo sopra TLS) o Digest (hash con nonce); 407 vale per i proxy. Content-Type porta il tipo MIME (tipo/sottotipo; parametri come charset e boundary), Accept e gli altri header Accept-* guidano la negoziazione. Un URI (RFC 3986) e' scheme://userinfo@host:porta/percorso?query#frammento, con percent-encoding %HH per i byte non ammessi e regole per risolvere i riferimenti relativi.Caching, autenticazione, tipi MIME e URI in HTTP →, sezione sui moduli), text/plain (da non usare). Un form HTML invia solo GET e POST; PUT e DELETE richiedono JavaScript (Web service, XML, JSON, SOAP e RESTUn web service e' un servizio software accessibile via rete da altri programmi, con messaggi in formato standard su HTTP; i formati di dati sono XML (marcatori annidati, attributi, namespace, validazione con XSD) e JSON (RFC 8259: oggetti, array, stringhe, numeri, true, false, null; piu' compatto e diretto per i linguaggi di programmazione); SOAP e' un protocollo di messaggi XML (Envelope con Header facoltativo e Body, Fault per gli errori) inviati di solito con una POST HTTP e descritti da un file WSDL; REST e' uno stile architetturale (Fielding) in cui il servizio espone risorse identificate da URI e le manipola con i metodi HTTP: GET legge, POST crea, PUT sostituisce, PATCH modifica, DELETE elimina, con codici di stato significativi (200, 201 con Location, 204, 400, 404, 409), senza stato sul server, con cache e interfaccia uniforme.Web service, XML, JSON, SOAP e REST →).
Validazione nativa
Il browser controlla i campi prima di inviare, se il form ha gli attributi giusti; in caso di errore blocca l'invio e mostra un messaggio sul primo campo errato.
| attributo | controlla |
|---|---|
required |
campo non vuoto (per select, un valore diverso dall'option con value="") |
type="email", url, number, date... |
formato del valore |
minlength, maxlength |
lunghezza del testo |
min, max, step |
intervallo e passo di numeri, date, ore |
pattern="[A-Za-zÀ-ÿ' ]+" |
espressione regolare, che deve coincidere con tutto il valore; title spiega il formato nel messaggio |
min="08:00" max="19:00" step="1800" su un type="time" accetta ore da 08:00 a 19:00 a passi di 30 minuti. Alcuni dettagli da conoscere:
- si può dare un aspetto ai campi con le pseudo-classi CSS
:valide:invalid; minlengthemaxlengthsono controllati solo dopo che l'utente ha modificato il campo: un valore impostato da JavaScript non genera errore (provato in un browser);novalidatesulform(oformnovalidatesul pulsante) spegne tutto;- la validazione si può estendere con JavaScript (
setCustomValidity, JavaScript - linguaggio, DOM ed eventiJavaScript (standard ECMAScript, Ecma-262) è il linguaggio dei browser: tipizzato dinamicamente, con sette tipi primitivi (number, string, boolean, undefined, null, bigint, symbol) e gli oggetti (anche array e funzioni); typeof null vale "object" per un errore storico; == converte i tipi, === no (si usa sempre ===); valori falsy: false, 0, 0n, "", null, undefined, NaN. let e const hanno visibilità di blocco e una zona morta prima della dichiarazione, var visibilità di funzione e hoisting; const impedisce di riassegnare il nome, non di modificare l'oggetto. Funzioni: dichiarazione (hoisted), espressione, arrow function (this lessicale), parametri predefiniti, rest e spread, destructuring. Array: map, filter, reduce, find, some, every, sort (senza comparatore ordina come stringhe). Closure: una funzione ricorda le variabili dell'ambiente in cui è nata. Eventi: addEventListener; propagazione in tre fasi (cattura, target, bolla), stopPropagation, preventDefault, delegazione con event.target e closest. DOM: albero di nodi; querySelector, createElement, append, replaceChildren, textContent (sicuro) contro innerHTML (rischio di XSS), classList, dataset. Moduli ES (type="module", import e export) sono differiti e in modalità strict. Event loop: un solo thread, call stack, coda dei task (setTimeout, eventi) e coda dei microtask (promise, await) svuotata dopo ogni task: l'esecuzione asincrona (fetch, async e await, Promise.all) è alla base di AJAX e il codice lungo blocca la pagina.JavaScript - linguaggio, DOM ed eventi →; esempio completo nell'esercizio Esercizio - Form HTML di prenotazione con validazione nativa e in JavaScript (applicazione web)); - è un servizio all'utente, non una difesa: chiunque può inviare una richiesta senza passare dal form (con
curlo con gli strumenti per sviluppatori del browser). Il server rifà sempre i controlli (Organizzazione fisica dei dati e accesso programmatico alle basi di datiUn DBMS è formato da un gestore delle connessioni, un parser, un ottimizzatore che sceglie il piano di esecuzione usando le statistiche del catalogo, un esecutore, i metodi di accesso (heap, ordinato, hash, B-tree, indici), il buffer manager e il gestore delle transazioni (lock e log). Il costo si misura in accessi a blocchi del disco. L'ottimizzatore riscrive l'espressione algebrica (selezioni e proiezioni il prima possibile, prodotto con selezione = join, ordine dei join) e sceglie gli algoritmi: scansione o indice per le selezioni, nested loop, block nested loop, index nested loop, sort-merge o hash join per i join (con 1000 e 100 blocchi, 10 pagine di buffer: 11 mila accessi con block nested loop, 3300 con hash join). La progettazione fisica sceglie organizzazione dei file, indici ed eventuale denormalizzazione in base al carico. Le applicazioni accedono ai dati con SQL incorporato, interfacce a livello di chiamata (ODBC, JDBC, DB-API di Python), ORM o routine memorizzate: connessione, cursore, execute con parametri, fetch, commit o rollback. Mai concatenare l'input dell'utente nell'SQL (SQL injection): query parametrizzate. Un'applicazione web è a tre livelli: browser, server applicativo (HTTP senza stato, sessioni e cookie) e DBMS.Organizzazione fisica dei dati e accesso programmatico alle basi di dati →: query parametrizzate e SQL injection).
Accessibilità di base
L'accessibilità (accessibility) è fare in modo che la pagina sia usabile da chi non vede, non usa il mouse o ha una vista debole. Con HTML ben scritto si ottiene gran parte del risultato:
langsuhtml;altsu ogni immagine;labelsu ogni campo;th scopeecaptionnelle tabelle;- gerarchia dei titoli ordinata (
h1,h2,h3, senza scegliere il livello per la grandezza: quella è compito di CSS); - elementi nativi al posto di quelli imitati: un
<button>è focalizzabile con Tab, si attiva con Invio e Spazio e il lettore di schermo lo annuncia come pulsante; un<div onclick>non fa nulla di questo; - testi dei link significativi: "Elenco aule", non "clicca qui";
- tutto raggiungibile e utilizzabile da tastiera, con il focus visibile (non togliere il contorno senza sostituirlo);
- contrasto sufficiente fra testo e sfondo; l'informazione non affidata solo al colore;
- ARIA (attributi
role,aria-label,aria-live...) solo quando non esiste un elemento nativo: la prima regola di ARIA è non usarla se HTML basta. Esempio utile:<p id="esito" role="status">fa leggere al lettore di schermo il messaggio di conferma quando cambia;<nav aria-label="Principale">distingue duenav.
Esempio completo
La pagina dell'applicazione, con header, nav, main a due section, footer, la tabella e il form sopra, è composta così:
<body>
<header>
<h1>Prenotazione delle aule</h1>
<nav aria-label="Principale">
<ul>
<li><a href="#prenotazioni">Prenotazioni</a></li>
<li><a href="#nuova">Prenota</a></li>
</ul>
</nav>
</header>
<main>
<section id="prenotazioni"> <h2>Prenotazioni del 19 ottobre 2026</h2> <!-- table --> </section>
<section id="nuova"> <h2>Nuova prenotazione</h2> <!-- form --> </section>
</main>
<footer>
<p>Dati di esempio. <a href="mailto:aule@example.org">Segnala un problema</a></p>
</footer>
</body>Il lato server che riceve il POST (la servlet PrenotazioniServlet) e la tabella costruita da JavaScript invece che scritta a mano sono nell'esercizio Esercizio - Tabella delle prenotazioni costruita con il DOM e filtrata (applicazione web).
Errori tipici
- Dimenticare
<!DOCTYPE html>o<meta charset>: lettere accentate rotte, modalità quirks. - Campo senza
name: non viene inviato. labelsenzaforoforche non coincide con l'id.method="get"per un'operazione che modifica dati, o per una password.<img>senzaalt;<div>al posto di<button>.- Annidamenti illegali (
<p><div>): il parser corregge e il DOM cambia. - Usare le tabelle per l'impaginazione.
- Fidarsi della validazione nativa come unico controllo.
- Saltare livelli di titolo (da
h1ah4) per ottenere un aspetto.
Domande d'esame
- Differenza fra GET e POST nell'invio di un form. GET: campi nell'URI (query string), richiesta sicura e idempotente, messa in cache e nei segnalibri, dati visibili. POST: campi nel corpo, per modifiche di stato, non idempotente,
Content-Typeapplication/x-www-form-urlencodedomultipart/form-data. Esempio con il form di prenotazione. - Perché usare
header,nav,main,sectioninvece didiv? Hanno un significato che i lettori di schermo e i motori di ricerca capiscono (punti di riferimento), rendono il CSS più chiaro;divè neutro.mainè unico. - Scrivere un form per prenotare un'aula con validazione nativa. Campi
aula_id(select,required),giorno(type="date"),ora_inizioeora_fine(type="time",min,max),studente(required,minlength,pattern), tutti conlabel forenameuguale alla colonna; spiegare che il server deve rifare i controlli.
Versione ripasso
Documento. <!DOCTYPE html> (modalità standard), <html lang="it">, <head> con meta charset="UTF-8", meta viewport, title, link rel="stylesheet", script defer; <body>. Attributi booleani senza valore (required); nomi di tag indifferenti alle maiuscole; elementi vuoti br, img, input, meta. Il parser corregge invece di fallire: aggiunge tbody, chiude i p davanti ai blocchi.
Semantica. header, nav, main (uno), section, article, aside, footer, figure, time: danno ruoli e punti di riferimento; div e span sono neutri. Titoli h1-h6 in gerarchia. strong/em hanno significato, b/i solo aspetto.
Link e immagini. href assoluto, relativo, #frammento, mailto:; target="_blank" con rel="noopener". img con alt (vuoto se decorativa), width, height.
Tabelle. table, caption, thead/tbody, tr, th scope="col|row", td, colspan, rowspan. Solo per dati.
Form.
action,method(getpredefinito),enctype.- Si invia solo ciò che ha
name;label for=iddel campo. - Tipi:
text,email,number,date,time,checkbox,radio,hidden,file; piùselect/option,textarea,button. - GET: campi nella query string (
?giorno=2026-10-19&studente=Dall%27Olio+Anna), sicuro e idempotente, nei segnalibri; POST: nel corpo (aula_id=1&giorno=2026-10-19&ora_inizio=09%3A00), per modificare lo stato, non idempotente. enctype:application/x-www-form-urlencoded(predefinito),multipart/form-data(file). Codifica: spazio+, altri%XX.- Un form HTML invia solo GET e POST (Caching, autenticazione, tipi MIME e URI in HTTPLa cache HTTP riusa le risposte senza contattare il server finche' sono fresche (Cache-Control: max-age, Expires; in mancanza una durata euristica pari a circa il 10% del tempo trascorso da Last-Modified) e, quando sono scadute, le rivalida con una richiesta condizionale (If-None-Match con ETag, If-Modified-Since con Last-Modified) alla quale il server risponde 304 senza corpo; no-store vieta di memorizzare, no-cache obbliga a rivalidare, private esclude le cache condivise. L'autenticazione usa 401 con WWW-Authenticate e la risposta Authorization: Basic (base64 di utente:password, solo sopra TLS) o Digest (hash con nonce); 407 vale per i proxy. Content-Type porta il tipo MIME (tipo/sottotipo; parametri come charset e boundary), Accept e gli altri header Accept-* guidano la negoziazione. Un URI (RFC 3986) e' scheme://userinfo@host:porta/percorso?query#frammento, con percent-encoding %HH per i byte non ammessi e regole per risolvere i riferimenti relativi.Caching, autenticazione, tipi MIME e URI in HTTP →).
Validazione nativa. required, minlength, maxlength, min, max, step, pattern (su tutto il valore), type; novalidate la spegne; minlength conta solo dopo la modifica dell'utente. Comoda ma aggirabile: il server rifà i controlli (Organizzazione fisica dei dati e accesso programmatico alle basi di datiUn DBMS è formato da un gestore delle connessioni, un parser, un ottimizzatore che sceglie il piano di esecuzione usando le statistiche del catalogo, un esecutore, i metodi di accesso (heap, ordinato, hash, B-tree, indici), il buffer manager e il gestore delle transazioni (lock e log). Il costo si misura in accessi a blocchi del disco. L'ottimizzatore riscrive l'espressione algebrica (selezioni e proiezioni il prima possibile, prodotto con selezione = join, ordine dei join) e sceglie gli algoritmi: scansione o indice per le selezioni, nested loop, block nested loop, index nested loop, sort-merge o hash join per i join (con 1000 e 100 blocchi, 10 pagine di buffer: 11 mila accessi con block nested loop, 3300 con hash join). La progettazione fisica sceglie organizzazione dei file, indici ed eventuale denormalizzazione in base al carico. Le applicazioni accedono ai dati con SQL incorporato, interfacce a livello di chiamata (ODBC, JDBC, DB-API di Python), ORM o routine memorizzate: connessione, cursore, execute con parametri, fetch, commit o rollback. Mai concatenare l'input dell'utente nell'SQL (SQL injection): query parametrizzate. Un'applicazione web è a tre livelli: browser, server applicativo (HTTP senza stato, sessioni e cookie) e DBMS.Organizzazione fisica dei dati e accesso programmatico alle basi di dati →); estensione con setCustomValidity (JavaScript - linguaggio, DOM ed eventiJavaScript (standard ECMAScript, Ecma-262) è il linguaggio dei browser: tipizzato dinamicamente, con sette tipi primitivi (number, string, boolean, undefined, null, bigint, symbol) e gli oggetti (anche array e funzioni); typeof null vale "object" per un errore storico; == converte i tipi, === no (si usa sempre ===); valori falsy: false, 0, 0n, "", null, undefined, NaN. let e const hanno visibilità di blocco e una zona morta prima della dichiarazione, var visibilità di funzione e hoisting; const impedisce di riassegnare il nome, non di modificare l'oggetto. Funzioni: dichiarazione (hoisted), espressione, arrow function (this lessicale), parametri predefiniti, rest e spread, destructuring. Array: map, filter, reduce, find, some, every, sort (senza comparatore ordina come stringhe). Closure: una funzione ricorda le variabili dell'ambiente in cui è nata. Eventi: addEventListener; propagazione in tre fasi (cattura, target, bolla), stopPropagation, preventDefault, delegazione con event.target e closest. DOM: albero di nodi; querySelector, createElement, append, replaceChildren, textContent (sicuro) contro innerHTML (rischio di XSS), classList, dataset. Moduli ES (type="module", import e export) sono differiti e in modalità strict. Event loop: un solo thread, call stack, coda dei task (setTimeout, eventi) e coda dei microtask (promise, await) svuotata dopo ogni task: l'esecuzione asincrona (fetch, async e await, Promise.all) è alla base di AJAX e il codice lungo blocca la pagina.JavaScript - linguaggio, DOM ed eventi →).
Accessibilità. lang, alt, label, th scope, gerarchia dei titoli, elementi nativi (button, non div onclick), uso da tastiera con focus visibile, contrasto, testi dei link chiari, ARIA solo se serve (role="status", aria-label).
Errori tipici
- Campo senza
name,labelsenzafor. - GET per modificare dati o per password.
imgsenzaalt.- Annidamenti illegali.
- Tabelle per l'impaginazione.
- Validazione solo nel browser.
Contesto: Linguaggi di markup - SGML, HTML e XMLUn linguaggio di markup aggiunge al testo marcatori che ne descrivono la struttura. SGML (ISO 8879, 1986) è il metalinguaggio da cui derivano HTML fino alla 4.01 e XML 1.0 (W3C, 1998, un sottoinsieme semplificato); HTML5 ha un proprio algoritmo di parsing, tollerante, e non è né SGML né XML. Un documento XML è ben formato se rispetta la sintassi (un'unica radice, tag annidati e chiusi, attributi tra virgolette, nomi con maiuscole e minuscole distinte, entità per i caratteri speciali) ed è valido se in più rispetta uno schema. La DTD dichiara elementi (ELEMENT: EMPTY, ANY, #PCDATA, sequenza con la virgola, scelta con |, cardinalità ? * +) e attributi (ATTLIST: CDATA, ID, IDREF, enumerazioni; #REQUIRED, #IMPLIED, #FIXED); non ha tipi di dato e non conosce i namespace. XML Schema (XSD) è scritto in XML e ha tipi (xs:date, xs:positiveInteger), restrizioni con pattern, minOccurs e maxOccurs, key e keyref. I namespace (xmlns, xmlns:prefisso) identificano il vocabolario con un URI; gli attributi senza prefisso non appartengono a nessun namespace. XML è rigido e adatto a documenti e configurazioni (web.xml, pom.xml), HTML è tollerante e ha un vocabolario fisso; JSON è l'alternativa più compatta per scambiare dati e non ha attributi, schema standard o contenuto misto.Linguaggi di markup - SGML, HTML e XML →, CSS3 - selettori, cascata, box model e layoutCSS descrive la presentazione: regole selettore { proprietà: valore }. Selettori: tipo, classe (.a), id (#a), attributo ([type="date"]), universale, combinatori (spazio discendente, > figlio, + fratello adiacente, ~ fratelli seguenti), pseudo-classi (:hover, :focus-visible, :nth-child, :not, :checked) e pseudo-elementi (::before, ::after). Cascata: tra più regole che toccano la stessa proprietà vince, nell'ordine, l'importanza (!important vince, e lo stile inline batte gli stili normali), poi la specificità (a,b,c) = (id, classi+attributi+pseudo-classi, tipi+pseudo-elementi) confrontata come numeri uno alla volta da sinistra, infine l'ordine di comparsa (l'ultima vince). Ereditarietà: color, font, line-height, text-align passano ai figli; margin, padding, border, background, width no; inherit, initial, unset la controllano. Box model: content, padding, border, margin; con content-box width è solo il contenuto, con border-box include padding e bordo; i margini verticali adiacenti collassano nel maggiore. display: block, inline, inline-block, none, flex, grid. position: static, relative, absolute (rispetto all'antenato posizionato), fixed, sticky. Flexbox è per una dimensione (justify-content, align-items, gap, flex-grow, flex-wrap), grid per due (grid-template-columns, fr, repeat, minmax, gap). Responsive: meta viewport, unità relative (rem, %, fr), media query @media (min-width), approccio mobile-first.CSS3 - selettori, cascata, box model e layout →, Esercizio - Form HTML di prenotazione con validazione nativa e in JavaScript (applicazione web). Scheletro del documento.
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Prenotazione aule - Dipartimento</title>
<link rel="stylesheet" href="stile.css">
<script src="app.js" defer></script>
</head>
<body> ...header, nav, main (section), footer... </body>
</html>meta viewport serve al responsive sui telefoni; <!DOCTYPE html> evita la modalità quirks; meta charset va nei primi 1024 byte.
Come corregge il parser (provato in un browser):
| sorgente | DOM |
|---|---|
<table><tr><td> |
aggiunge <tbody> |
<p>uno<p>due |
due paragrafi |
<p>testo<div> |
il p si chiude prima del div |
<ul><li>A<li>B |
ogni li chiude il precedente |
Tabella accessibile.
<table>
<caption>Aule prenotate nel giorno scelto</caption>
<thead><tr><th scope="col">Aula</th><th scope="col">Dalle</th><th scope="col">Alle</th><th scope="col">Studente</th></tr></thead>
<tbody><tr><th scope="row">Aula A1</th><td>09:00</td><td>11:00</td><td>Rossi</td></tr></tbody>
</table>Form di prenotazione.
<form action="/prenotazioni" method="post">
<label for="giorno">Giorno</label>
<input type="date" id="giorno" name="giorno" required>
<label for="studente">Cognome</label>
<input type="text" id="studente" name="studente" required minlength="2" maxlength="40" pattern="[A-Za-zÀ-ÿ' ]+">
<button type="submit">Prenota</button>
</form>Richieste prodotte.
GET /prenotazioni?giorno=2026-10-19&studente=Dall%27Olio+Anna HTTP/1.1
POST /prenotazioni HTTP/1.1
Content-Type: application/x-www-form-urlencoded
aula_id=1&giorno=2026-10-19&ora_inizio=09%3A00&ora_fine=11%3A00&studente=Dall%27Olio+%26+RossiNel corpo di un POST una & che fa parte del valore diventa %26. multipart/form-data con i file. Con type="date" e type="time" i valori sono nei formati delle colonne SQL.
Domande d'esame, tracce.
- GET contro POST: dove vanno i campi, sicuro e idempotente, segnalibri, dati visibili.
- Perché gli elementi semantici invece di
div: ruoli e punti di riferimento,mainunico. - Form di prenotazione con validazione nativa; il server rifà i controlli.
Esercizi su questo argomento
- Esercizio - Calcolo della specificità e della cascata (applicazione web)
- Esercizio - Form HTML di prenotazione con validazione nativa e in JavaScript (applicazione web)
- Esercizio - Pagina AJAX per creare e cancellare prenotazioni (applicazione web)
- Esercizio - Tabella delle prenotazioni costruita con il DOM e filtrata (applicazione web)