Ogni elemento HTML di una pagina diventa un nodo del DOM, e ogni nodo ha un costo. Il browser deve calcolarne lo stile, posizionarlo nel layout, disegnarlo e tenerlo in memoria. Finché i nodi sono qualche centinaio non ci si accorge di nulla; quando diventano decine di migliaia, come accade con elenchi lunghi, tabelle estese, menu enormi o costruttori di pagine che annidano contenitori su contenitori, ogni operazione diventa più lenta.
Dove si paga un DOM grande
Il costo non si concentra in un solo momento:
- caricamento: più HTML da scaricare e analizzare, più nodi da costruire;
- calcolo degli stili: a ogni modifica il browser deve verificare quali regole CSS si applicano a quali elementi, e con selettori complessi il lavoro cresce con il numero dei nodi;
- layout: cambiare la dimensione di un elemento può costringere a ricalcolare la posizione di molti altri;
- interazioni: un clic che aggiunge una classe al
bodypuò innescare il ricalcolo degli stili dell'intera pagina, e questo tempo finisce nel ritardo di presentazione dell'INP; - memoria: sui dispositivi con poca RAM, pagine molto grandi rischiano rallentamenti generali o il ricaricamento della scheda.
Lighthouse segnala un DOM eccessivo e indica il numero totale di elementi, la profondità massima e l'elemento con più figli: tre indizi utili per capire dove intervenire.
Ridurre i nodi alla fonte
L'intervento più efficace è non creare nodi inutili:
- contenitori annidati: molti temi e costruttori visuali avvolgono ogni blocco in quattro o cinque
divsenza funzione. Con CSS Grid e Flexbox la stessa disposizione si ottiene quasi sempre con un solo livello; - contenuto nascosto: menu mobili, finestre modali, schede non attive e varianti di prodotto spesso sono presenti nel DOM fin dall'inizio, solo nascosti. Si possono generare al momento dell'apertura;
- icone SVG ripetute: lo stesso SVG incollato cento volte moltiplica i tracciati; un elemento
useche rimanda a un simbolo definito una volta sola è molto più leggero; - paginazione o caricamento progressivo: mostrare mille prodotti in una sola pagina raramente serve all'utente.
content-visibility: rimandare il lavoro fuori schermo
Quando il contenuto deve restare nella pagina, per esempio un articolo lungo o una pagina di documentazione, la proprietà CSS content-visibility permette al browser di saltare il rendering delle sezioni fuori dallo schermo:
.sezione {
content-visibility: auto;
contain-intrinsic-size: auto 600px;
}
Con auto, il browser calcola layout e disegno di una sezione solo quando si avvicina all'area visibile. Il contenuto resta nel DOM: è raggiungibile con la ricerca nella pagina, dai lettori di schermo e dalla navigazione con le ancore.
La seconda riga è importante. Una sezione saltata non ha dimensioni note, e senza indicazioni verrebbe trattata come alta zero: la barra di scorrimento cambierebbe continuamente e il contenuto salterebbe. contain-intrinsic-size fornisce una stima; con la parola chiave auto il browser ricorda la dimensione reale dopo il primo rendering e la riusa.
Quando usarla e quando no
| Situazione | Consiglio |
|---|---|
| Articoli lunghi divisi in sezioni | Ottimo candidato |
| Elenchi di schede con altezza simile | Buon candidato, con stima precisa |
| Contenuto nella parte iniziale della pagina | Inutile, viene comunque disegnato |
| Elementi con altezza molto variabile | Possibili salti di scorrimento |
Va applicata a blocchi di una certa consistenza, non a ogni singolo paragrafo: su elementi minuscoli il beneficio è nullo e il rischio di salti aumenta.
La proprietà contain
Prima di content-visibility esisteva già contain, che dice al browser che un elemento è indipendente dal resto della pagina. Con contain: layout paint, per esempio, una modifica all'interno di un widget non costringe a ricalcolare il layout dell'intera pagina, e il disegno non esce dai suoi confini. È utile per componenti che si aggiornano spesso, come un orologio, un contatore o un pannello di notifiche.
Virtualizzare gli elenchi lunghi
Per elenchi con migliaia di righe, come una tabella di dati o un registro di eventi, la soluzione più radicale è la virtualizzazione: si creano nel DOM solo le righe visibili più un piccolo margine, e mentre l'utente scorre si riciclano gli stessi nodi cambiandone il contenuto. Il numero di nodi resta costante qualunque sia la lunghezza dell'elenco.
La virtualizzazione ha un prezzo: le righe non presenti non sono trovate dalla ricerca del browser e vanno gestite con attenzione per l'accessibilità. Per questo conviene riservarla alle interfacce applicative e preferire paginazione o content-visibility per i contenuti editoriali.
Misurare il risultato
Nel pannello Performance di DevTools, le voci Recalculate Style e Layout mostrano quanti elementi sono stati coinvolti in ogni ricalcolo. Confrontarle prima e dopo l'intervento, magari su un'interazione specifica come l'apertura di un menu, rende evidente il guadagno. Nel mio lavoro, ridurre l'annidamento di un tema e generare i menu solo all'apertura ha spesso migliorato l'INP più di qualsiasi ottimizzazione del JavaScript.
In sintesi
- Ogni nodo del DOM costa in stili, layout, disegno e memoria.
- Elimina contenitori inutili e genera contenuti nascosti solo quando servono.
content-visibility: autoconcontain-intrinsic-sizesalta il rendering fuori schermo.containisola i componenti che si aggiornano spesso.- Per elenchi enormi nelle applicazioni, la virtualizzazione mantiene costante il numero di nodi.