CSS object-fit and aspect-ratio
Images and videos come in many shapes. aspect-ratio and object-fit help you put them in neat boxes without stretching or squashing them.
The aspect-ratio Property
An aspect ratio is the width compared to the height. A widescreen video is 16 / 9. A square is 1 / 1.
With aspect-ratio, you set only the width, and the browser works out the height.
Example
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; }
.box {
width: 200px;
margin-bottom: 12px;
display: grid;
place-items: center;
color: white;
}
.square { aspect-ratio: 1 / 1; background-color: #264de4; }
.video { aspect-ratio: 16 / 9; background-color: crimson; }
.story { aspect-ratio: 9 / 16; width: 100px; background-color: seagreen; }
</style>
</head>
<body>
<div class="box square">1 / 1</div>
<div class="box video">16 / 9</div>
<div class="box story">9 / 16</div>
</body>
</html>Try it Yourself »| Ratio | Common use |
|---|---|
1 / 1 | Profile pictures, product thumbnails |
4 / 3 | Old photos and screens |
16 / 9 | YouTube videos, banners |
9 / 16 | Phone stories and reels |
Responsive Videos
An embedded YouTube video uses an <iframe> with a fixed size. Make it fill the width and keep its shape:
Example
iframe {
width: 100%;
height: auto;
aspect-ratio: 16 / 9;
}aspect-ratio also helps page speed. When the browser knows the shape of an image box before the image loads, the page does not jump around while loading.
The Stretching Problem
If you give an image both a width and a height that do not match its real shape, the browser stretches it. Faces look too wide or too thin.
object-fit tells an <img> or <video> how to fill its box instead.
| Value | What happens |
|---|---|
fill | Stretches to fill the box (the default, can distort) |
contain | Shows the whole image inside the box; empty space may appear |
cover | Fills the whole box; parts of the image may be cut off |
none | Keeps the image's real size |
scale-down | Like none or contain, whichever is smaller |
object-fit in Action
The image in this example is 400px wide and 200px tall (a wide picture made with SVG), shown in square 150px boxes.
Example
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; }
.row { display: flex; gap: 16px; flex-wrap: wrap; }
figure { margin: 0; text-align: center; }
img {
width: 150px;
height: 150px;
border: 2px solid #333333;
background-color: #f1f5f9;
}
.fill { object-fit: fill; }
.contain { object-fit: contain; }
.cover { object-fit: cover; }
</style>
</head>
<body>
<div class="row">
<figure>
<img class="fill" alt="Blue banner with a gold circle" src="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='400' height='200'><rect width='400' height='200' fill='%23264de4'/><circle cx='200' cy='100' r='70' fill='gold'/></svg>">
<figcaption>fill</figcaption>
</figure>
<figure>
<img class="contain" alt="Blue banner with a gold circle" src="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='400' height='200'><rect width='400' height='200' fill='%23264de4'/><circle cx='200' cy='100' r='70' fill='gold'/></svg>">
<figcaption>contain</figcaption>
</figure>
<figure>
<img class="cover" alt="Blue banner with a gold circle" src="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='400' height='200'><rect width='400' height='200' fill='%23264de4'/><circle cx='200' cy='100' r='70' fill='gold'/></svg>">
<figcaption>cover</figcaption>
</figure>
</div>
</body>
</html>Try it Yourself »- With
fill, the circle becomes an oval: the image is stretched. - With
contain, the whole banner fits, with grey space above and below. - With
cover, the box is full and the circle stays round, but the sides are cut off.
object-position
When cover cuts part of the image, object-position chooses which part stays visible. It works like background-position.
Example
.avatar {
width: 120px;
height: 120px;
object-fit: cover;
object-position: top; /* keep the top: usually the face */
border-radius: 50%;
}Other values: center (default), bottom, left, right, or exact positions like 30% 20%.
A Product Card Grid
Shops get product photos in all shapes. Together, these two properties give every card the same neat picture area:
Example
.product img {
width: 100%;
aspect-ratio: 4 / 3;
object-fit: cover;
border-radius: 8px;
}Every image is now the full card width, in a 4:3 shape, and nothing is stretched.
For logos, use contain so no part of the logo is ever cut off. For photos, cover usually looks best.
Exercise
Exercise
You want every product photo to fill its square box completely, without stretching. Which value do you use?
