CSS inutilizzato e stati dinamici

La rimozione automatica del CSS inutilizzato fotografa la pagina in un solo stato: menu aperti, moduli con errori e carrelli restano senza stile. Perché succede e come ridurre il CSS alla fonte.

Un foglio di stile ridotto dell’87%: restano le regole della pagina appena caricata, spariscono quelle di menu aperto, schede attive, errori dei moduli e carrello; sullo smartphone il menu aperto appare come un elenco di link senza stile

“Riduci il CSS inutilizzato” è uno dei suggerimenti che Lighthouse mostra più spesso, soprattutto sui siti WordPress costruiti con temi multiuso e page builder. Il numero accanto al suggerimento è eloquente: decine o centinaia di kilobyte di regole che la pagina scarica ma non usa. La tentazione di risolvere con un clic è forte, e molti plugin di ottimizzazione offrono proprio questo: una funzione che analizza la pagina, elimina tutto ciò che non serve e serve un foglio di stile ridotto al minimo.

Funziona, finché l’utente non tocca nulla. Il CSS “inutilizzato” al momento dell’analisi spesso è semplicemente CSS non ancora utilizzato: quello del menu aperto, del messaggio di errore di un modulo, della scheda selezionata, del carrello che scorre di lato. In questo articolo vediamo perché il CSS pesa sulle performance, come funziona la rimozione automatica e perché gli stati dinamici ne sono il punto debole.

Perché il CSS pesa sulle performance

Il CSS è una risorsa bloccante per il rendering: finché il browser non ha scaricato ed elaborato i fogli di stile presenti nell’<head>, non disegna nulla sullo schermo. Ogni kilobyte in più allunga il download, e ogni regola in più aumenta il lavoro necessario per costruire il modello degli stili e calcolare l’aspetto di ciascun elemento. Su uno smartphone di fascia media, con una connessione mobile, la differenza tra 40 e 400 kilobyte di CSS si vede direttamente in FCP e LCP.

Il pannello Coverage dei DevTools di Chrome mostra quanta parte dei fogli di stile viene effettivamente applicata alla pagina. Su un sito basato su un tema multiuso non è raro che l’80 o il 90% del CSS risulti inutilizzato: stili di componenti mai usati, varianti per decine di layout, regole di plugin caricate su ogni pagina anche quando servono solo in una.

Come funziona la rimozione automatica

Gli strumenti che generano il CSS “usato” seguono quasi sempre lo stesso schema. Un browser senza interfaccia carica la pagina, osserva quali selettori corrispondono a elementi presenti nel documento e produce un foglio di stile che contiene solo quelli. Il risultato viene inserito nella pagina al posto dei fogli originali, che a seconda della configurazione vengono eliminati, caricati in modo asincrono o caricati solo alla prima interazione.

Il limite è nel concetto stesso di “usato”: l’analisi fotografa la pagina in un solo istante, in un solo stato, spesso a una sola larghezza dello schermo. Tutto ciò che in quel momento non esiste nel documento viene considerato superfluo.

Gli strumenti più evoluti conservano comunque le pseudo-classi come :hover, :focus o :checked, perché possono verificare che il selettore di base corrisponda a un elemento. Non possono invece sapere quali classi il JavaScript aggiungerà in seguito, né quali elementi verranno inseriti nel documento dopo il caricamento: per loro, ciò che non esiste nell’istante dell’analisi non esisterà mai.

Il problema degli stati dinamici

Una pagina moderna non è un documento statico. Il JavaScript aggiunge e toglie classi in risposta a quello che fa l’utente, e ognuna di queste classi ha le proprie regole di stile. Un esempio tipico è il menu mobile:

/* CSS del tema */
.mobile-nav { display: none; }
.menu-open .mobile-nav { display: block; position: fixed; inset: 0; }

/* JavaScript del tema */
toggle.addEventListener( 'click', () => {
	document.body.classList.toggle( 'menu-open' );
} );

Al momento dell’analisi il body non ha la classe menu-open: la seconda regola non corrisponde a nulla e viene eliminata. Il risultato, per l’utente, è un menu che al tocco compare come un elenco di link privo di stile sopra il contenuto, oppure non compare affatto. Lo stesso accade in decine di situazioni comuni:

  • header che diventa compatto e fisso dopo lo scorrimento;
  • schede, fisarmoniche e slider con la classe dell’elemento attivo;
  • finestre modali, popup promozionali e banner del consenso ai cookie;
  • mini carrello laterale, avvisi di prodotto aggiunto, messaggi di WooCommerce;
  • stati di errore e di conferma dei moduli, campi obbligatori evidenziati;
  • varianti visibili solo agli utenti che hanno effettuato l’accesso o a chi ha già prodotti nel carrello.

A questi si aggiungono le differenze tra modelli di pagina, come una scheda prodotto con varianti rispetto a una senza, e tra larghezze dello schermo, quando l’analisi avviene a una sola risoluzione. Sono proprio i punti in cui l’utente sta per fare qualcosa di importante: aprire il menu, scegliere una taglia, completare un modulo, arrivare al carrello.

La safelist: una toppa da manutenere

Per limitare i danni, gli strumenti di rimozione permettono di indicare una safelist: un elenco di selettori, o di parti di selettori, da conservare sempre. È una soluzione necessaria ma fragile. Qualcuno deve conoscere tutte le classi dinamiche usate dal tema, dai plugin e dagli script di terze parti, e aggiornare l’elenco a ogni modifica. Un aggiornamento del tema che rinomina una classe, un nuovo plugin che introduce un proprio popup, una campagna che attiva un banner diverso: ogni cambiamento può riaprire il problema senza che nessuno se ne accorga, perché i test automatici di performance continuano a mostrare lo stato iniziale, che è perfetto.

C’è poi un costo operativo. Il CSS ridotto va generato per ogni pagina o modello, conservato e rigenerato quando cambiano contenuti o stili. Se la rigenerazione non avviene, o avviene in ritardo, la pagina viene servita con un foglio di stile che non corrisponde più al markup, con errori visibili difficili da collegare alla causa.

Quando i fogli originali arrivano dopo

Molte configurazioni cercano un compromesso: servono subito il CSS ridotto e caricano i fogli completi in modo asincrono, o alla prima interazione. È più sicuro dell’eliminazione totale, perché prima o poi tutte le regole arrivano. Ma sposta il problema su altre metriche. Se i fogli completi arrivano mentre l’utente sta già leggendo, gli elementi possono cambiare dimensione o posizione, con salti di layout che peggiorano il CLS. Se arrivano alla prima interazione, il primo tocco deve aspettare anche il download e l’applicazione degli stili, con effetti sull’INP. È lo stesso schema del delay del JavaScript: il costo non sparisce, cambia momento.

Il Critical CSS, cioè l’inserimento nella pagina dei soli stili necessari alla parte visibile al caricamento seguito dal foglio completo non bloccante, segue la stessa logica e ha gli stessi rischi, se lo stile critico è incompleto. Funziona bene quando è generato e verificato per ogni modello di pagina, male quando è generato una volta e dimenticato.

Ridurre il CSS alla fonte

L’approccio più robusto è evitare che il CSS superfluo arrivi alla pagina, invece di eliminarlo dopo averlo generato. In pratica significa:

  1. Dividere gli stili per modello di pagina. Gli stili della home, degli articoli, delle schede prodotto e del checkout vanno in file separati, caricati solo dove servono. Anche questo sito funziona così: gli stili delle sezioni della home non vengono mai caricati nelle pagine del blog, e viceversa.
  2. Caricare gli stili dei blocchi solo se presenti. WordPress, con i temi a blocchi, può includere il CSS di ciascun blocco soltanto nelle pagine che lo contengono.
  3. Disattivare gli stili dei plugin dove non servono. Il foglio di stile del modulo di contatto non ha motivo di essere caricato in tutte le pagine del sito, né quello dello slider in pagine senza slider.
  4. Ripulire in fase di sviluppo, non a runtime. Strumenti come PurgeCSS possono eliminare le regole inutilizzate durante la build, analizzando template e script con una safelist versionata insieme al codice e verificata dai test, invece di una fotografia della pagina in produzione.
  5. Valutare il peso del tema e del page builder. Quando la maggior parte del CSS appartiene a funzioni che il sito non usa, la soluzione duratura è un tema più essenziale, non uno strumento che ne nasconda il peso.

Come verificare che nulla si sia rotto

Qualunque sia la strategia scelta, la verifica deve riguardare gli stati, non solo la pagina appena caricata. Il pannello Coverage può registrare l’utilizzo del CSS mentre si interagisce con la pagina: aprendo il menu, selezionando una variante e inviando un modulo vuoto si vede crescere la quota di regole utilizzate, e diventa evidente quanto CSS “inutilizzato” fosse in realtà solo in attesa.

Per i siti in cui la continuità conta, conviene automatizzare il controllo con test di regressione visiva che fotografano gli stati principali: menu aperto su mobile, carrello con prodotti, modulo con errori, banner del consenso, ciascuno alle larghezze più usate. E dopo ogni modifica alla gestione del CSS, osservare nei dati degli utenti reali l’andamento del CLS e dell’INP, oltre che di LCP.

In sintesi

Il CSS inutilizzato è un problema reale, perché blocca il rendering e rallenta la prima visualizzazione della pagina. La rimozione automatica lo affronta fotografando la pagina in un solo stato, e per questo elimina anche le regole di menu, moduli, carrelli e componenti interattivi che l’utente incontrerà un istante dopo. Safelist e caricamenti ritardati limitano i danni, ma richiedono manutenzione continua e spostano il costo su CLS e INP.

Ogni scorciatoia ha un costo da misurare. Il modo più affidabile per avere poco CSS è non caricarne di superfluo: stili divisi per modello di pagina, caricati solo dove servono, ripuliti in fase di sviluppo e verificati su tutti gli stati che contano per l’utente e per il business.

IL PROSSIMO PASSO

Partiamo
dal tuo sito.

Raccontaci il progetto, i problemi che riscontri e i tuoi obiettivi. Definiremo insieme un intervento su misura.

Richiedi un’analisi

Ti porta al modulo della pagina Contatti.

MANAGED SERVER S.R.L.info@corewebvitals.it +39 02 5656 9681

Lunedì – venerdì · 09:30 – 19:30

Preferisci un modulo online?
Contattaci su managedserver.it ↗