Sviluppo web
aspect-ratio: come togliere il CLS dalle immagini, senza wrapper
aspect-ratio riserva lo spazio dell'immagine prima che il file arrivi e toglie il layout shift. Dove va messo nel markup e dove peggiora le cose.
In sintesi
- aspect-ratio riserva lo spazio prima del caricamento: è la correzione più economica al CLS da immagini.
- Va messo sull'immagine, non sul contenitore che contiene anche testo.
- Il vecchio wrapper con padding-top funziona ancora, ma serve solo per browser senza aspect-ratio.
Risposta breve: dichiarare aspect-ratio su un'immagine riserva lo spazio prima che il file arrivi e toglie il layout shift. Un tag img senza dimensioni è la causa più frequente di CLS su una pagina di contenuto.
Perché il CLS si muove
Il browser non conosce l'altezza di un'immagine finché non ha i byte. Fino a quel momento la riserva a zero, poi la allarga e spinge in basso tutto quello che segue. Il punteggio CLS misura proprio questo spostamento, in proporzione a quanto e a quanta pagina si muove.
Il codice
.thumb {
display: block;
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
height: auto;
}
/* la riserva vale anche prima che il file arrivi */
.thumb-slot {
aspect-ratio: 16 / 9;
background: color-mix(in oklab, currentColor 8%, transparent);
}
Il vecchio trucco del wrapper con padding-top: 56.25% risolve lo stesso problema. Serve ancora quando devi supportare browser senza aspect-ratio: il comando qui sotto calcola la percentuale da una misura di progetto.
# percentuale del wrapper classico per un'immagine 1200x675
node -e "const w=1200,h=675;console.log((100*h/w).toFixed(2)+'%'+' / ratio '+(w/h).toFixed(4))"
# atteso: 56.25% / ratio 1.7778
Le tre larghezze che contano
| Contesto | Rischio | Cosa fare |
|---|---|---|
| Colonna di testo | L'immagine a piena larghezza sposta il paragrafo | aspect-ratio sull'immagine |
| Griglia di card | Righe di altezza diversa dopo il caricamento | Lo stesso rapporto su tutte le card |
| Hero con immagine LCP | L'immagine è l'elemento più grande della pagina | width e height nell'attributo, più fetchpriority="high" |
Il supporto copre Chrome 88, Firefox 89 e Safari 15. Non è una funzionalità da polyfillare: sul browser che non la conosce il layout resta quello di prima, senza rotture.
Il limite
aspect-ratio fissa il rapporto, non l'altezza: se il contenuto cresce dentro un contenitore con rapporto fisso, esce o viene tagliato. Applicalo all'immagine, o a un contenitore che contiene solo media, mai al blocco che contiene testo.
Come verificarlo
- Apri Performance, spunta Layout Shift e ricarica: le barre viola devono sparire.
- Disattiva la cache e ricarica tre volte: il valore deve restare stabile, non dipendere dalla velocità.
- Prova a 360 px: la card non deve cambiare altezza fra prima e dopo il caricamento.
- Controlla il ritaglio con
object-fit: cover: il soggetto deve restare in cornice.
Dove continuare
Nel catalogo: blocco gallery, componenti e icone. Le guide: layout shift da immagini e CLS, cause e correzioni; il confronto: Tailwind contro CSS Modules.
Domande frequenti
Basta width e height sull'attributo?
Sì per il layout, perché il browser ne ricava il rapporto. aspect-ratio in CSS serve quando le dimensioni cambiano con la viewport o quando l'immagine la generi tu.
Funziona anche con video e iframe?
Sì, <code>aspect-ratio</code> è una proprietà generale. Su un iframe evita il salto quando il player si monta, che è il caso più visibile su una pagina prodotto.
Devo tenere il wrapper con padding-top?
Solo se il pubblico include browser senza supporto. Altrimenti aggiunge un nodo e una regola da mantenere.
Come gestisco immagini di rapporti diversi?
Con <code>object-fit: cover</code> e un rapporto unico per la griglia, oppure con rapporti dichiarati per variante. Il rapporto misto nella stessa riga rompe l'allineamento.
Il CLS scende davvero a zero?
Non sempre: restano font, banner e contenuti iniettati. Togliere lo shift delle immagini elimina però la voce più grande su una pagina di contenuto.