Corso di CSS / Immagini e video responsive: aspect-ratio e object-fit
I media responsive richiedono sia una dimensione sensata degli elementi che una regola deliberata per adattare il loro contenuto. aspect-ratio aiuta a stabilire le proporzioni di un riquadro, mentre object-fit: cover o contain determina se un'immagine o un video riempie o si adatta all'interno di quel riquadro.
Separare le dimensioni intrinseche dalle dimensioni di visualizzazione
Se l'originale è 400×300, il rapporto è 4:3. Se la larghezza del display è 288px e si mantengono le stesse proporzioni, l'altezza del display è 216px. Gli attributi width e height in HTML forniscono informazioni sulla dimensione e sul rapporto dell'immagine, mentre il CSS controlla la dimensione visualizzata sulla pagina. Piuttosto che risolvere il problema rimuovendo gli attributi di dimensione nell’HTML, controlla quale valore viene sovrascritto nel CSS.
img { max-width: 100%; height: auto; }
/* Instead of forcing the small original size to grow, it is reduced to fit the parent. */
max-width: 100% è un limite massimo che impedisce che diventi più largo del suo genitore e non aumenta incondizionatamente l'originale piccolo. width: 100% è una specifica che riempie la larghezza del genitore, quindi può essere ingrandito oltre l'originale. La nitidezza della foto e la dimensione del download sono questioni separate. Puoi scaricare file grandi anche se sembrano piccoli con CSS, e quando usi srcset · sizes, il browser seleziona un'immagine tra i candidati, quindi devi controllare la dimensione di visualizzazione sullo schermo e il file effettivamente selezionato.
Usa aspect-ratio per il ridimensionamento automatico
aspect-ratio: 16 / 9 utilizza il rapporto di 16 di larghezza su 9 di altezza per calcolare la dimensione. Se la larghezza è di 288px, l'altezza è di 162px. Almeno una dimensione deve essere automatica affinché possano essere effettuati calcoli proporzionali, e se sia la larghezza che l'altezza sono fisse, quella dimensione fissa ha la precedenza anche se si inserisce questa proprietà. È inoltre possibile verificare le condizioni di calcolo della dimensione del rapporto di aspetto di MDN.
.thumbnail { width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; }
.gallery { display: flex; flex-wrap: wrap; gap: 1rem; align-items: flex-start; }
La lezione Allineamento Flexbox, ritorno a capo, gap, grow e shrink spiega come l’allineamento possa uniformare l’altezza delle immagini nella stessa riga. Per calcolare automaticamente l'altezza quando si posizionano immagini con rapporti originali diversi affiancate, verificare anche il align-items: flex-start del genitore oppure align-self dell'elemento. Se il rapporto sembra lo stesso dopo aver modificato solo l'altezza in auto, la regola di allineamento del genitore potrebbe esserne la causa.
In pratica, il box-sizing è unificato come border-box. Quando si aggiungono bordi o padding, diventa importante misurare la dimensione e le proporzioni della scatola. Le immagini negli esempi di confronto qui sotto non hanno bordi o padding per evitare confusione.
Confronta il comportamento di adattamento e ritaglio
| Valore di object-fit | rapporto originale | area di visualizzazione | dettaglio |
|---|---|---|---|
| fill | Può essere ampliato per adattarsi all'area | Riempie il riquadro | Possibile distorsione a seconda dell'originale |
| cover | mantieni | Riempi senza spazi vuoti | Se il rapporto è diverso, alcune parti vengono tagliate. |
| contain | mantieni | Adatta per adattare tutto l'elemento | Se il rapporto è diverso, rimane spazio vuoto |
Adattare un'immagine 4:3 in un riquadro 16:9 con cover taglia la parte superiore e inferiore. Il posizionamento centrato divide il taglio tra loro; object-position: center top preserva la parte superiore e taglia di più sotto. Controlla il contenuto importante ai bordi prima di scegliere un taglio. I background CSS usano scelte di adattamento correlate ma hanno un ruolo diverso per contenuto e accessibilità rispetto alle immagini HTML. Vedi Colori e immagini di sfondo: cover e contain.
Lo schema seguente illustra la stessa immagine di pratica geometrica al suo rapporto originale, con cover, con contain e con cover allineata in alto. Confronta le fasce superiore verde e inferiore rossa e lo spazio vuoto ai lati. Il cerchio centrale rimane visibile in questi esempi, quindi le bande ai bordi rendono più facile identificare il ritaglio. L'esempio completo in HTML qui sotto ti permette di riprodurre il confronto.
Esegui il confronto delle quattro immagini
Salvalo come image-ratio.html e aprilo. L'immagine originale è inclusa come dati SVG all'interno del file, quindi non è necessaria alcuna immagine esterna. Gli attributi width e height di ciascuna immagine mantengono le informazioni originali di 400×300 mentre il CSS determina le dimensioni di visualizzazione e il rapporto del riquadro.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>image-ratio.html</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font: 1rem/1.6 sans-serif; color: #243447; }
h1, h2, p { margin-top: 0; } a { color: #145f8f; }
a:focus-visible, button:focus-visible, input:focus-visible { outline: 3px solid #ac4100; outline-offset: 3px; }
main { width: min(100%, 65rem); margin-inline: auto; padding: 1rem; }
.gallery { display: flex; flex-wrap: wrap; gap: 1rem; align-items: flex-start; }
.sample { width: min(100%, 18rem); margin: 0; }
.sample img { display: block; width: 100%; height: auto; background: #e2e2e2; }
.sample p { margin: .5rem 0 0; } .cover, .contain { aspect-ratio: 16 / 9; }
.cover { object-fit: cover; } .contain { object-fit: contain; }
.top { object-position: center top; }
</style>
</head>
<body>
<main><h1>Compare the size and cropping of the same picture</h1><div class="gallery"><div class="sample"><img class="" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22400%22%20height%3D%22300%22%20viewBox%3D%220%200%20400%20300%22%3E%3Crect%20width%3D%22400%22%20height%3D%22300%22%20fill%3D%22%23287699%22%2F%3E%3Crect%20width%3D%22400%22%20height%3D%2235%22%20fill%3D%22%23205c32%22%2F%3E%3Crect%20y%3D%22265%22%20width%3D%22400%22%20height%3D%2235%22%20fill%3D%22%239e3131%22%2F%3E%3Ccircle%20cx%3D%22200%22%20cy%3D%22150%22%20r%3D%2270%22%20fill%3D%22%23f6ae4c%22%2F%3E%3Crect%20x%3D%2212%22%20y%3D%22120%22%20width%3D%2230%22%20height%3D%2260%22%20fill%3D%22white%22%2F%3E%3Crect%20x%3D%22358%22%20y%3D%22120%22%20width%3D%2230%22%20height%3D%2260%22%20fill%3D%22white%22%2F%3E%3C%2Fsvg%3E" width="400" height="300" alt="Top green band, bottom red band and center orange circle"><p>Original 4:3</p></div>
<div class="sample"><img class="cover" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22400%22%20height%3D%22300%22%20viewBox%3D%220%200%20400%20300%22%3E%3Crect%20width%3D%22400%22%20height%3D%22300%22%20fill%3D%22%23287699%22%2F%3E%3Crect%20width%3D%22400%22%20height%3D%2235%22%20fill%3D%22%23205c32%22%2F%3E%3Crect%20y%3D%22265%22%20width%3D%22400%22%20height%3D%2235%22%20fill%3D%22%239e3131%22%2F%3E%3Ccircle%20cx%3D%22200%22%20cy%3D%22150%22%20r%3D%2270%22%20fill%3D%22%23f6ae4c%22%2F%3E%3Crect%20x%3D%2212%22%20y%3D%22120%22%20width%3D%2230%22%20height%3D%2260%22%20fill%3D%22white%22%2F%3E%3Crect%20x%3D%22358%22%20y%3D%22120%22%20width%3D%2230%22%20height%3D%2260%22%20fill%3D%22white%22%2F%3E%3C%2Fsvg%3E" width="400" height="300" alt="Top green band, bottom red band and center orange circle"><p>16:9 cover, center</p></div>
<div class="sample"><img class="contain" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22400%22%20height%3D%22300%22%20viewBox%3D%220%200%20400%20300%22%3E%3Crect%20width%3D%22400%22%20height%3D%22300%22%20fill%3D%22%23287699%22%2F%3E%3Crect%20width%3D%22400%22%20height%3D%2235%22%20fill%3D%22%23205c32%22%2F%3E%3Crect%20y%3D%22265%22%20width%3D%22400%22%20height%3D%2235%22%20fill%3D%22%239e3131%22%2F%3E%3Ccircle%20cx%3D%22200%22%20cy%3D%22150%22%20r%3D%2270%22%20fill%3D%22%23f6ae4c%22%2F%3E%3Crect%20x%3D%2212%22%20y%3D%22120%22%20width%3D%2230%22%20height%3D%2260%22%20fill%3D%22white%22%2F%3E%3Crect%20x%3D%22358%22%20y%3D%22120%22%20width%3D%2230%22%20height%3D%2260%22%20fill%3D%22white%22%2F%3E%3C%2Fsvg%3E" width="400" height="300" alt="Top green band, bottom red band and center orange circle"><p>16:9 contain</p></div>
<div class="sample"><img class="cover top" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22400%22%20height%3D%22300%22%20viewBox%3D%220%200%20400%20300%22%3E%3Crect%20width%3D%22400%22%20height%3D%22300%22%20fill%3D%22%23287699%22%2F%3E%3Crect%20width%3D%22400%22%20height%3D%2235%22%20fill%3D%22%23205c32%22%2F%3E%3Crect%20y%3D%22265%22%20width%3D%22400%22%20height%3D%2235%22%20fill%3D%22%239e3131%22%2F%3E%3Ccircle%20cx%3D%22200%22%20cy%3D%22150%22%20r%3D%2270%22%20fill%3D%22%23f6ae4c%22%2F%3E%3Crect%20x%3D%2212%22%20y%3D%22120%22%20width%3D%2230%22%20height%3D%2260%22%20fill%3D%22white%22%2F%3E%3Crect%20x%3D%22358%22%20y%3D%22120%22%20width%3D%2230%22%20height%3D%2260%22%20fill%3D%22white%22%2F%3E%3C%2Fsvg%3E" width="400" height="300" alt="Top green band, bottom red band and center orange circle"><p>16:9 cover, top</p></div>
</div></main>
</body>
</html>
- Su schermi larghi, assicurarsi che la larghezza di ogni immagine sia limitata a 18rem. Con un font root di 16px, è larga 288px, l'originale è alta 216px, e l'area rimanente in 16:9 è alta 162px.
- Cambiare solo l'altezza di
.sample imga 300px. Anche se viene applicato il rapporto 16:9, verificare che l'area sia 288×300px a causa dell'altezza fissa e ripristinarla su auto. - Cambiare solo l'align-items di
.gallerysu stretch. Assicurarsi che l'altezza del contenitore per la stessa riga sia la stessa, ma che le proporzioni dell'immagine all'interno del contenitore siano mantenute, e tornare a flex-start. In questo esempio, l'elemento Flex è un contenitore di esempio, non un'immagine. Nelle configurazioni dove le immagini sono posizionate direttamente come elementi Flex, l'altezza automatica può aumentare, quindi l'allineamento deve essere verificato. - Modifica soltanto object-position di
.topin center bottom. Questa volta, assicurati che la banda rossa rimanga e che la banda verde venga tagliata, e poi ripristina center top.
Il file SVG nell'esempio ha anche la caratteristica di mantenere le proporzioni delle forme. Se l'area di visualizzazione di un elemento immagine è errata e crea spazio vuoto, il cerchio non sarà necessariamente distorto. Invece di guardare solo la forma, controlla la larghezza e l'altezza dell'elemento img negli strumenti per sviluppatori.
Ridimensionare il contenuto video all'interno della sua finestra di visualizzazione
Nell'esercizio qui sotto, un video muto di 400×300 creato per questa lezione viene visualizzato con object-fit: contain in un’area 16:9. Non ci sono informazioni audio o dei sottotitoli nel video, solo il movimento del cerchio arancione, che viene utilizzato per controllare gli spazi superiori, inferiori e laterali e le operazioni di riproduzione. L'indirizzo del file video WebM per esercitarsi è incluso nell'esempio. Per eseguire l’esempio senza rete, scarica prima il file e posizionalo nella stessa cartella dell'HTML, sostituendo l'indirizzo di origine con il nome del file.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>video-ratio.html</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font: 1rem/1.6 sans-serif; color: #243447; }
h1, h2, p { margin-top: 0; } a { color: #145f8f; }
a:focus-visible, button:focus-visible, input:focus-visible { outline: 3px solid #ac4100; outline-offset: 3px; }
main { width: min(100%, 34rem); margin-inline: auto; padding: 1rem; }
video { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: contain; background: #111; }
</style>
</head>
<body>
<main><h1>Video display ratio</h1>
<p id="video-description">This silent sample video shows an orange circle moving on a blue background. Play and pause it to compare aspect ratios.</p>
<video controls preload="metadata" width="400" height="300" aria-describedby="video-description">
<source src="https://www.codingfactory.net/wp-content/uploads/css-media-ratio-motion-v1.webm" type="video/webm">
<a href="https://www.codingfactory.net/wp-content/uploads/css-media-ratio-motion-v1.webm">Download the sample video</a>
</video></main>
</body>
</html>
L’attributo controls consente all'utente di utilizzare operazioni del browser come riproduci/pausa, e preload="metadata" è un suggerimento che richiede di leggere le informazioni meta prima della riproduzione. Il metodo di download effettivo è determinato dal tuo browser. Poiché non abbiamo incluso l'autoplay, premi il pulsante di riproduzione per confermare. Se cambi solo object-fit in cover, puoi vedere la differenza in quanto l'area rimane la stessa e i contenuti in alto e in basso vengono tagliati. Dopo la conferma, ripristina su contain.
object-fit adatta il contenuto negli elementi sostituiti come immagini e video. Non ridimensiona il contenuto iframe di un video incorporato nello stesso modo: dai a quell'iframe un contenitore con proporzioni appropriate e dimensiona l’iframe all’interno del contenitore. Diversamente da questo esempio decorativo silenzioso, un video con audio significativo necessita di alternative adeguate, come i sottotitoli. Vedi MDN: object fit, MDN: video.





