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

ContestoRischioCosa fare
Colonna di testoL'immagine a piena larghezza sposta il paragrafoaspect-ratio sull'immagine
Griglia di cardRighe di altezza diversa dopo il caricamentoLo stesso rapporto su tutte le card
Hero con immagine LCPL'immagine è l'elemento più grande della paginawidth 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.