Sprite CSS: quando sono ancora utili e come crearne uno
Molti tutorial sugli sprite CSS iniziano ancora con la stessa frase del 2009: gli sprite riducono le richieste HTTP, quindi rendono il sito più veloce. L’argomento si basava su un vincolo HTTP/1.1 che non esiste più su un server moderno. Ecco la versione onesta: cosa giustifica davvero ancora uno sprite, cosa no e l’esatto background-position e i calcoli retina per crearne uno che funzioni.
Cos’è davvero uno sprite CSS
Uno sprite CSS è un unico file immagine contenente molti elementi grafici separati, più il CSS che ne mostra soltanto uno alla volta. Non richiede ritagli né JavaScript. All’elemento viene assegnato un valore fisso di width e height, l’intero foglio viene impostato come suo background-image, e background-position fa scorrere il foglio dietro l’elemento affinché l’icona desiderata cada nel riquadro visibile. Il riquadro è una finestra; il foglio di sprite è un grande foglio di carta trascinato dietro di essa.
Il dettaglio che sorprende inizialmente è che gli scostamenti sono negativo. Non sposti la finestra verso l’icona: sposti il foglio affinché l’icona raggiunga la finestra. Per mostrare un’icona il cui angolo superiore sinistro si trova a 96 pixel dal bordo sinistro del foglio, sposti il foglio di 96 pixel verso sinistra, cioè background-position: -96px 0.
Un esempio concreto. Supponi di inserire cinque icone di 24×24 in una sola riga, con 8 pixel di spazio tra loro, iniziando a 8 pixel dal bordo sinistro e a 8 pixel da quello superiore. Il foglio misura così 160×32. Il bordo sinistro della terza icona si trova a 8 + 24 + 8 + 24 + 8 = 72 pixel e quello superiore a 8 pixel. La regola è:
| Dichiarazione | Cosa fa |
|---|---|
| background-image: url("/sprite.png") | Carica l’intero foglio dietro l’elemento |
| background-repeat: no-repeat | Impedisce la ripetizione del foglio e la comparsa di altre icone ai bordi |
| background-position: -72px -8px | Sposta il foglio di 72px a sinistra e 8px in alto affinché la terza icona arrivi all’origine |
| width: 24px; height: 24px | Limita la finestra esattamente a un’icona: è ciò che nasconde il resto |
| display: inline-block | Permette a un elemento in linea come uno span di rispettare larghezza e altezza |
Cambia solo i due numeri in background-position e ottieni un’icona diversa dallo stesso file. Questo è l’intero meccanismo.

La parte onesta: HTTP/2 ha cambiato i calcoli
Gli sprite CSS furono inventati per superare un limite specifico. Con HTTP/1.1, un browser apriva poche connessioni TCP per origine, comunemente sei, e ciascuna poteva gestire una sola richiesta alla volta. Quaranta file di icone significavano quaranta richieste in coda attraverso sei canali, ognuna con il costo dell’apertura della connessione e della latenza di andata e ritorno. Unirle in un file trasformava quaranta richieste serializzate in una. Su una connessione ad alta latenza non era una micro-ottimizzazione: spesso era il miglioramento più grande disponibile per una pagina.
HTTP/2 usa il multiplexing. Molte richieste condividono simultaneamente una connessione, senza blocco della prima richiesta a livello HTTP, e le intestazioni vengono compresse tra richieste. Il problema specifico per cui furono inventati gli sprite è quasi svanito. Se un tutorial nel 2026 dice che gli sprite sono più veloci perché riducono le richieste e si ferma lì, è stato scritto per un web che non esiste più.
Perché esiste allora questo articolo? Perché “il motivo originale è scomparso” non significa “non c’è alcun motivo”. Diversi vantaggi reali sopravvivono al multiplexing e meritano una decisione:
- Il costo per richiesta non scende a zero. Le richieste multiplexate costano poco, ma non sono gratuite. Ognuna contiene ancora intestazioni, una ricerca nella cache e un posto nel pianificatore di risorse del browser. Con cinque icone è trascurabile. Con duecento icone piccole è misurabile e lo sprite lo riduce a una voce.
- La gestione della cache diventa più semplice. Un file significa una voce di cache, un Cache-Control politica, un nome di file con hash da invalidare. Duecento file di icone con versioni separate costituiscono un insieme di elementi di build e distribuzione che va gestito e di solito non lo è.
- Versionamento atomico. Tutte le icone vengono distribuite insieme, quindi non puoi ritrovarti con un set aggiornato a metà, con tre icone dalla cache nel vecchio stile e le altre nuove. Per il rilascio di un sistema di design è una vera proprietà di correttezza, non soltanto ordine.
- Nessuno sfarfallio da icona mancante. Caricato il foglio, ogni icona è disponibile subito. Le icone singole compaiono una alla volta al completamento delle richieste, soprattutto dove è più fastidioso: una barra strumenti o griglia visibile senza scorrere.
- Cambiamenti di stato senza latenza. Uno stato al passaggio del mouse o attivo situato altrove nello stesso foglio è già scaricato. Con file separati, l’immagine al passaggio del mouse viene spesso richiesta soltanto al primo passaggio, producendo uno sfarfallio vuoto quando l’utente tocca il pulsante per la prima volta. È sempre stato uno degli argomenti più forti a favore degli sprite e HTTP/2 non lo ha indebolito.
Quando non usare uno sprite CSS
Una raccomandazione credibile deve includere i casi in cui la risposta è no, e per gli sprite CSS ce ne sono diversi.
- Le icone monocromatiche e scalabili appartengono a SVG. Un elemento in linea <svg> oppure uno sprite SVG costruito da <symbol> e <use> si adatta a qualsiasi dimensione senza calcoli retina ed eredita il colore tramite currentColor. Per un normale set di icone dell’interfaccia è semplicemente uno strumento migliore, ed è il motivo per cui i fogli di sprite hanno perso silenziosamente gran parte della loro quota nei sistemi di icone.
- Una sola icona non giustifica mai uno sprite. Se hai una sola immagine, usa una sola immagine. Lo sprite aggiunge gestione delle coordinate e una fase di compilazione senza alcun vantaggio.
- Icone che cambiano indipendentemente. Il versionamento atomico ha due facce. Se cambia un’icona, l’intera voce di cache del foglio viene invalidata e ogni utente lo riscarica tutto. Un set di icone che cambia frequentemente non è adatto agli sprite.
- Qualsiasi elemento che richieda ricolorazione o temi. Uno sprite raster incorpora i suoi colori. Modalità scura, temi di marca e colori degli stati richiedono quindi un secondo foglio o fragili trucchi con filtri. È il vantaggio strutturale più evidente di SVG.
- Icone che devono rispondere alle dimensioni del carattere. Gli sprite sono vincolati a dimensioni in pixel. Se le icone devono adattarsi a em insieme al testo, un approccio vettoriale lo gestisce, mentre uno sprite ti ostacola.
Sprite, sprite SVG, SVG in linea o font di icone
| Approccio | Si ridimensiona nitidamente | Ricolora tramite CSS | Richieste | Memorizzazione nella cache | Accessibilità |
|---|---|---|---|---|---|
| Sprite CSS (raster) | No — pixel fissi, serve un foglio 2x | No, solo trucchi con filtri | Uno per tutte le icone | Eccellente, un file di lunga durata | Immagine di sfondo invisibile alle tecnologie assistive: richiede un’etichetta testuale |
| Sprite SVG (symbol + use) | Sì, qualsiasi dimensione | Sì, tramite currentColor | Uno per tutte le icone | Eccellente, un file | Nel DOM, supporta title e ARIA |
| SVG in linea per icona | Sì, qualsiasi dimensione | Sì, controllo CSS completo | Zero, incorporato nell’HTML | Nessuna — reinviato con ogni pagina | La migliore, interamente nel DOM |
| Font di icone | Sì, varia con font-size | Sì, tramite color | Un file di font | Buono | Scarsa — i glifi vengono letti o sostituiti da font alternativi |
Leggi la tabella come decisione, non classifica. La grafica raster multicolore, come bandiere, loghi, stemmi illustrati e schermate di icone, non può diventare sensatamente uno sprite SVG: è l’ambito in cui gli sprite CSS restano la risposta corretta, non una soluzione obsoleta.
Crearne uno
Il flusso di lavoro comprende quattro passaggi, e solo il terzo è laborioso da eseguire a mano.
- Raccogli le icone. Esporta alle dimensioni finali di visualizzazione, oppure al doppio: vedi la sezione retina. Mantieni dimensioni coerenti quando puoi; una griglia uniforme semplifica i calcoli delle coordinate e rende il CSS regolare.
- Impacchettali in un foglio. Una riga semplice o una griglia fissa sono più facili da gestire; un impacchettatore sfrutta meglio lo spazio quando le dimensioni variano. Lascia uno spazio tra le icone.
- Leggi le coordinate. Ogni icona richiede x, y, larghezza e altezza in pixel del foglio. Farlo a mano in un editor è il punto in cui il lavoro sugli sprite va storto: una lettura errata di un pixel mostra una striscia dell’icona vicina e nulla spiega perché.
- Scrivi il CSS. Una regola di base condivisa più una piccola regola per icona.
La regola di base condivisa conta più di quanto sembri. Ogni icona deve avere lo stesso background-image, background-repeat: no-repeat, e display: inline-block. Ripetendo il background-image Un URL in cinquanta regole non è un problema di prestazioni: il browser lo recupera comunque una sola volta. È però un problema di manutenzione: rinomina il foglio per invalidare la cache e avrai cinquanta punti da modificare anziché uno. Il modello prevede quindi una classe di base con tutto ciò che è condiviso e classi per icona con solo posizione e dimensioni:
| Regola | Contenuti |
|---|---|
| .sprite | background-image, background-repeat: no-repeat, display: inline-block |
| .sprite-search | background-position: -8px -8px; width: 24px; height: 24px |
| .sprite-settings | background-position: -40px -8px; width: 24px; height: 24px |
Nel markup è <span class="sprite sprite-search"></span>. In Sass la stessa idea viene solitamente espressa come segnaposto, %sprite-base, inserito in ogni regola delle icone tramite @extend — produce un unico selettore raggruppato nel risultato compilato anziché ripetere le dichiarazioni e mantiene il markup a una sola classe per icona.
Retina e HiDPI: il trucco di background-size
È la parte che la maggior parte delle guide salta o spiega male. Uno sprite raster disegnato a 1x appare sfocato su uno schermo 2x, e la soluzione non è cambiare gli offset: è creare il foglio a risoluzione doppia e poi indicare a CSS che il foglio ha metà delle sue dimensioni reali.
Riprendi l’esempio e raddoppia tutto all’esportazione: icone 48×48 pixel reali, spazio 16 e foglio 320×64 pixel reali. Ora imposta background-size: 160px 32px — esattamente metà delle dimensioni reali del foglio. Il browser riduce l’intero foglio in uno spazio di coordinate di 160×32 pixel CSS e mappa il dettaglio aggiuntivo sui pixel fisici del dispositivo su uno schermo HiDPI.
Il vantaggio è che gli altri numeri CSS restano nel sistema 1x. La terza icona è ancora background-position: -72px -8px con width: 24px; height: 24px, invariato, anche se i suoi pixel effettivi si trovano a 144, 16 nel file. Calcoli gli scostamenti una sola volta, in pixel CSS, e l’unico background-size dichiarazione sulla classe di base gestisce la mappatura della densità per tutte le icone contemporaneamente.
Ne derivano due conseguenze che vale la pena esplicitare. Primo, background-size appartiene alla regola di base condivisa, non va ripetuto per ogni icona. Secondo, non distribuire due fogli tramite una media query senza una valida ragione: il foglio 2x a metà dimensione appare corretto anche sugli schermi 1x, perché il browser lo riduce, quindi un solo foglio e una sola regola coprono entrambi i casi, al costo di un file più grande. Poiché un foglio di icone ben compresso è solitamente piccolo, il compromesso conviene e aggira i rapporti frazionari dei pixel del dispositivo come 1,5 e 2,5, dove una media query deve scegliere una parte e una delle due sarà sbagliata.
Varianti al passaggio del mouse e degli stati
La disposizione classica per elementi interattivi ha colonne per icone e righe per stati: predefinito nella prima, passaggio mouse nella seconda, attivo o disattivato nella terza. Le colonne non cambiano, quindi cambia solo Y e lo scostamento X rimane identico.
Con icone da 24 px e uno spazio di 8 px, la prima riga si trova a y = 8 e la seconda a y = 40. La regola predefinita della terza icona è background-position: -72px -8px e la sua regola al passaggio del mouse è background-position: -72px -40px. Se imposti il passo verticale come variabile, ad esempio --sprite-row: 32px — puoi esprimere una volta lo stato al passaggio del mouse sulla classe di base usando calc() rispetto a una variabile X per icona, anziché scrivere una seconda regola per ogni icona.
È qui che lo sprite supera davvero ancora i file separati: i pixel dello stato al passaggio del mouse arrivano insieme a quelli dello stato predefinito, quindi il primo passaggio del mouse è istantaneo. È anche il motivo per cui dovresti tenere gli stati sullo stesso foglio anziché separarli: un foglio separato per il passaggio del mouse reintroduce esattamente lo sfarfallio dovuto alla richiesta al primo passaggio che questa disposizione mirava a prevenire.
Margini e perché qui la contaminazione è più lieve che nei giochi
Impacchettare immagini adiacenti rende possibile che il campionatore oltrepassi il confine di un’icona e trascini il colore di una vicina. Nei motori di gioco è un rischio costante e noto perché le texture sono ridotte, dotate di mipmap, filtrate e disegnate con trasformazioni subpixel arbitrarie.
Gli sprite CSS vivono in un ambiente meno severo. Non ci sono mipmap, gli sfondi vengono normalmente composti a posizioni intere e, con un rapporto esatto 1:1 e senza trasformazioni, nessun campionamento attraversa il confine. Ma “meno severo” non significa “mai”: il problema compare in punti prevedibili, con rapporti dei pixel del dispositivo frazionari (1.5, 2.25, 3), zoom del browser a percentuali insolite, qualsiasi transform: scale() su un antenato, e il background-size riduzione dalla sezione retina: tutte operazioni che collocano i bordi delle icone su confini non interi dei pixel del dispositivo, dove il compositore deve interpolare.
La soluzione è uguale ed economica: piccoli spazi trasparenti, 2–4 pixel a 1x (4–8 a 2x), tra icone e lungo il bordo esterno. Costa poco e rimuove un’intera classe di segnalazioni “linea tenue a sinistra solo sul mio portatile”. Per estrusione, mipmap e potenze di due, l’equivalente nei motori è trattato in Impacchettamento atlanti sprite: margini, potenze di due e contaminazione.
Problemi comuni
- Icone vicine visibili ai bordi. Il riquadro dell’elemento è più grande dell’icona e mostra altro contenuto. Larghezza/altezza errate o margini interni lo gonfiano: verifica se box-sizing: border-box è attivo, perché cambia ciò che comprende la larghezza dichiarata.
- Dimenticare background-repeat: no-repeat. Il valore predefinito è repeat, quindi il foglio si ripete e frammenti di altre icone riempiono il riquadro. È facile non accorgersene quando l’icona si trova vicino all’origine del foglio e sembra quasi corretta.
- Uno span senza dimensioni. Gli elementi in linea ignorano width e height completamente, quindi un vuoto <span> con una classe sprite si riduce a dimensioni zero e non viene visualizzato nulla. Imposta display: inline-block (oppure block, oppure rendilo un elemento flex) nella classe di base.
- Foglio obsoleto dopo una ricostruzione. Reimpacchetti lo sprite, le coordinate cambiano, ma un visitatore abituale ha ancora il vecchio foglio in cache insieme al nuovo CSS: ogni icona è quindi leggermente sbagliata per lui e perfetta per te. Invalida la cache cambiando il nome del file a ogni ricostruzione (un hash del contenuto, sprite.a1b2c3.png) invece di affidarsi a una stringa di query o a ricaricamenti forzati da parte degli utenti.
- Scostamenti di mezzo pixel. Dimensioni dispari di icone, spazi o margini iniziali in un foglio 2x producono scostamenti frazionari dopo il dimezzamento, proprio ciò che causa aloni ai bordi. Mantieni pari tutte le dimensioni del foglio 2x.
Domande frequenti
Gli sprite CSS sono obsoleti nel 2026?
La motivazione originale è obsoleta, la tecnica no. Con HTTP/2 e HTTP/3 ridurre richieste non basta. Restano set con molte piccole immagini raster: una cache, versionamento atomico, niente comparsa graduale e stati mouse immediati. Per icone monocromatiche SVG ha davvero superato il raster: usarlo lì nel 2026 sceglie lo strumento peggiore.
Sprite CSS o sprite SVG: quale usare?
Scegli in base alla grafica, non alla distribuzione. Se le icone sono piatte, geometriche e monocromatiche o bicolori, usa uno sprite SVG: si ridimensiona senza un foglio 2x e si ricolora tramite currentColor, e risiede nel DOM, dove le tecnologie assistive possono raggiungerlo. Se le tue immagini sono fotografie, contengono molte sfumature o sono vere immagini raster multicolore, come bandiere, miniature di prodotti, loghi di piattaforme o pixel art, SVG non offre vantaggi e uno sprite CSS raster è la scelta giusta.
Quanto può diventare grande un foglio prima di creare problemi?
Due limiti distinti. Nella pratica, il foglio blocca il rendering di tutte le icone che contiene, quindi un foglio abbastanza grande da ritardare la prima visualizzazione non aiuta più: mantienilo nell’ordine di poche centinaia di kilobyte e separa le icone usate raramente, come schermate amministrative e pannelli delle impostazioni, in un secondo foglio caricato solo dove serve. Tecnicamente, browser e dispositivi mobili limitano le dimensioni delle immagini decodificate e la memoria complessiva delle tele; fogli molto grandi possono essere ridotti senza avvisi o non decodificarsi su telefoni con poca memoria. Un foglio che supera circa 2000 pixel per lato merita di essere diviso già solo per questo motivo, e ricorda che un foglio 2x ha già dimensioni doppie rispetto al progetto.
Posso ricolorare un’icona sprite con CSS?
Non davvero: è la risposta onesta, non quella comoda. I colori sono incorporati nel raster. Puoi approssimare con filter — concatenando invert, sepia, saturate, e hue-rotate per spingere un’icona nera verso una tonalità obiettivo, ma è un espediente nel senso letterale: i valori si trovano per tentativi o tramite un risolutore, non raggiungono un colore di marca esatto, falliscono sulla grafica multicolore e sono illeggibili per la prossima persona che lavora sul codice. Un secondo foglio nel colore alternativo è più trasparente di una catena di filtri. Se ricolorare è un vero requisito, quel requisito ti sta dicendo di usare SVG.
Impacchetta le icone in un foglio di sprite
Generatore di sprite prende le immagini inserite, le impacchetta con il margine scelto e scrive le coordinate, senza leggere manualmente gli scostamenti. Scegli CSS per una regola di base condivisa contenente background-image, background-repeat: no-repeat e display: inline-block, più una regola per ogni sprite con il suo valore negativo di background-position e larghezza e altezza in pixel: esattamente la struttura descritta sopra. Scegli SCSS e lo stesso risultato arriva come %sprite-base segnaposto che ogni regola di icona richiama tramite @extend. Scegli JSON per ottenere invece le coordinate grezze dei fotogrammi, da usare nei tuoi strumenti. Tutto funziona nel browser: non viene caricato nulla da nessuna parte.
Apri Generatore di fogli di sprite