Indice — 19 percorsiWeb Agency · Milano

My  Web  Lab

Guida operativa · Performance Web

Render-blocking: come eliminare CSS e JavaScript che frenano il sito

Le risorse render-blocking impediscono al browser di mostrare la pagina finché non le scarica e processa. Ecco come identificarle ed eliminarle per migliorare LCP e FCP.

Tempo di lettura: 13 min

Blog redesign · Performance Web

Render-blocking: come eliminare CSS e JavaScript che frenano il sito

Le risorse render-blocking sono CSS e JavaScript nel `<head>` che il browser deve scaricare e processare interamente prima di poter mostrare qualsiasi pixel della pagina. Ogni secondo di attesa si traduce direttamente in FCP (First Contentful Paint) e LCP più alti. La soluzione: inline il CSS critico, carica il CSS non critico in modo asincrono, e usa `defer` o `async` per tutti gli script non essenziali al render iniziale. Eliminare il render-blocking è spesso la singola ottimizzazione con il maggiore impatto sul punteggio Lighthouse.

Come il browser processa HTML: il blocking spiegato

Il browser legge l'HTML sequenzialmente dall'alto verso il basso costruendo il DOM. Quando incontra un `<link rel="stylesheet">` si ferma, scarica il CSS, costruisce il CSSOM, e solo dopo riprende. Quando incontra un `<script>` senza attributi si ferma, scarica il file, lo esegue, e solo dopo riprende. Su connessione 3G lenta con 5 CSS e 3 script nel head, questa sequenza di stop-and-wait può richiedere 3-4 secondi prima che l'utente veda qualcosa.

Il motivo per cui CSS è render-blocking: il browser non può renderizzare l'HTML senza il CSSOM completo, perché non saprebbe quale font size, colore, o display applicare agli elementi. Questo è per design, non un bug: renderizzare senza CSS produrrebbe un FOUC (Flash of Unstyled Content) inaccettabile. La soluzione non è rimuovere il CSS, ma ridurre il CSS nel critical path al minimo indispensabile e caricare il resto in modo asincrono.

CSS critico vs CSS non critico

Il CSS critico è solo quello necessario per renderizzare il contenuto above-the-fold: header, hero, font, colori principali. Tutto il resto — stili per footer, menu mobile, componenti nelle sezioni inferiori — è non critico. La tecnica del CSS critico inline consiste nell'estrarre queste poche regole (tipicamente 5-15 KB) e inserirle direttamente nell'HTML nel `<style>` tag nel `<head>`, eliminando la richiesta bloccante. Il CSS non critico viene poi caricato in modo asincrono.

Calcolare il CSS critico manualmente è impraticabile per siti complessi. Strumenti come `critical` (npm), `Penthouse`, o `critters` (usato internamente da Angular CLI e disponibile per Next.js) automatizzano l'estrazione: simulano il rendering della pagina a una data viewport e estraggono le regole CSS che "toccano" gli elementi visibili. Su Next.js con Tailwind CSS, il meccanismo di purge + ottimizzazione del bundle di Tailwind produce già CSS molto ridotti, ma il critical inline può comunque migliorare ulteriormente il FCP.

Caricare il CSS non critico in modo asincrono

Il trucco con `<link rel="stylesheet" media="print" onload="this.media='all'">` sfrutta il fatto che i CSS con `media="print"` non bloccano il render (il browser li scarica in bassa priorità senza bloccare). Quando il file è pronto l'event `onload` cambia `media` ad `all`, applicando gli stili. Il tag `<noscript>` garantisce il fallback per browser senza JavaScript. Questa tecnica è usata in produzione da Google stesso.

Un'alternativa moderna: `<link rel="preload" href="styles.css" as="style" onload="this.rel='stylesheet'">`. Il `preload` dice al browser di scaricare il CSS con alta priorità ma senza bloccare il render. Quando il download finisce, `onload` cambia `rel` in `stylesheet` applicando gli stili. È leggermente più aggressivo della tecnica `media="print"` (priorità di download più alta) e funziona meglio per CSS che devono essere disponibili rapidamente dopo il caricamento iniziale.

JavaScript: defer vs async, la differenza che conta

`defer` scarica lo script in parallelo con il parsing HTML e lo esegue dopo che il DOM è pronto, mantenendo l'ordine tra script con defer. `async` scarica in parallelo e esegue non appena il download finisce, interrompendo il parsing: l'ordine di esecuzione non è garantito. Regola pratica: usa `defer` per tutti gli script che dipendono dal DOM, `async` per script indipendenti come analytics. Mai nessun attributo per script critici necessari prima del render (ma questi devono essere minimali).

Una situazione comune che vediamo: Google Tag Manager nel `<head>` senza attributi, con 10+ tag configurati che si caricano tutti al page load. Il solo snippet GTM può aggiungere 200-400ms al TBT. La soluzione: carica GTM con `defer` (perde la capacità di firedare tag nel `<head>`, ma quasi nessun tag moderno ne ha bisogno), oppure carica GTM nella posizione corretta (`</body>`) invece del `<head>`. Per i tag che richiedono assolutamente il `<head>` (Consent Mode v2), configurali direttamente senza GTM.

Identificare le risorse render-blocking con PageSpeed Insights

PageSpeed Insights mostra esplicitamente le risorse render-blocking nella sezione "Opportunità" con la voce "Eliminate render-blocking resources" e una stima del risparmio in secondi. Ogni file elencato è un candidato da analizzare: è il CSS del tema WordPress intero? È uno script di terze parti caricato sincrono? Chrome DevTools → Performance → "Network" mostra visivamente quali risorse bloccano la barra di "First Paint". Nelle nostre realizzazioni di siti web questa ottimizzazione è sistematica.

Un metodo rapido per visualizzare il render-blocking: apri Chrome DevTools → Network tab → reload con cache disabilitata → nota le barre blu (HTML/JS/CSS) nel waterfall. Tutto ciò che è nella zona iniziale e blocca le barre successive è render-blocking. Le risorse render-blocking hanno solitamente una barra viola (CSS) o gialla (JS) che si estende dall'inizio del caricamento e durante la quale nessun'altra risorsa inizia il download. Questo pattern visivo è immediatamente riconoscibile con un po' di pratica.

Google Tag Manager: una soluzione e un problema

GTM (Google Tag Manager) è utile per centralizzare gli script di marketing, ma se il container GTM viene caricato in modo sincrono nel `<head>` aggiunge il suo peso al critical path. Soluzione: carica lo snippet GTM con `defer` (non sincrono), oppure posizionalo prima della chiusura del `</body>` invece che nel `<head>`. Attenzione: alcuni tag richiedono il `<head>` — in quel caso usa l'opzione "Consent Mode" per ridurre il codice bloccante.

Una strategia che adottiamo per i clienti con molti tag GTM: audita il container GTM e rimuovi i tag inutilizzati (spesso ci sono tag di campagne concluse o test mai rimossi). Poi classifica i tag rimanenti per priorità: analytics di base (GA4) → `afterInteractive`; pixel remarketing → `lazyOnload`; live chat → `lazyOnload`; consent management → sincrono nel `<head>` (inevitabile). Con questa classificazione, un container da 15 tag che bloccava il render per 600ms diventa un setup che aggiunge 0ms al FCP e LCP.

Font web: preload per eliminare il blocco

I font web non sono tecnicamente render-blocking nel senso tradizionale, ma il testo rimane invisibile (FOIT) finché il font non è caricato, causando un salto visivo (FOUT) che impatta il CLS e la percezione di velocità. Precarica i font essenziali con `<link rel="preload" href="/fonts/main.woff2" as="font" crossorigin>` nel `<head>`: il browser inizia il download con la massima priorità in parallelo con l'HTML. Su Next.js con `next/font` tutto questo è automatico.

La strategia font ottimale che implementiamo nei nostri progetti: self-host i font WOFF2 nel dominio del sito, preload del font principale (il font del body text) con alta priorità, `font-display: swap` per il font body (testo visibile subito con fallback, poi sostituito), `font-display: optional` per font decorativi non critici (se non carica in tempo viene saltato). Il risultato: zero FOIT, CLS vicino a zero da font, e nessuna richiesta esterna a Google Fonts. Per la gestione siti web dei clienti con WordPress, questo richiede 1-2 ore di configurazione ma ha un impatto immediato sul CLS.

Articolo a cura diMy Web Lab — Agenzia Web Milano

Siamo un team di designer e sviluppatori specializzati in SEO, Next.js e crescita digitale per PMI italiane. Costruiamo siti che portano traffico reale e clienti reali.

Lavora con noi →

Risorse correlate

Tutte le guide →

Hai un progetto in mente?

Parliamone.

Contattaci ora