object-fit and aspect-ratio
Crop and scale media with object-fit, lock boxes with aspect-ratio, and stop layout shift when images load.
- css
- object-fit
- aspect-ratio
Images and videos arrive with intrinsic dimensions that rarely match the UI slot. object-fit controls how the replaced content paints inside its box; aspect-ratio gives that box a stable shape before the bytes arrive so layout doesn’t jump.
Docs: MDN object-fit, object-position, aspect-ratio.
object-fit values
.thumb img {
width: 100%;
height: 100%;
object-fit: cover; /* fill box, crop overflow */
object-position: center;
}
| Value | Behavior |
|---|---|
fill |
Default — stretch to box (distorts) |
contain |
Fit entire image inside; letterbox possible |
cover |
Fill box; crop overflow |
none |
Intrinsic size |
scale-down |
Like none or contain, whichever is smaller |
.logo {
width: 8rem;
height: 3rem;
object-fit: contain;
object-position: left center;
}
.avatar {
width: 3rem;
height: 3rem;
border-radius: 50%;
object-fit: cover;
}
object-fit only applies when the element has a definite box — set both dimensions or one dimension + aspect-ratio/height from layout.
aspect-ratio
.video-wrap {
aspect-ratio: 16 / 9;
}
.video-wrap iframe,
.video-wrap video {
width: 100%;
height: 100%;
display: block;
object-fit: cover; /* for video poster frames / media */
}
.card__media {
aspect-ratio: 4 / 3;
overflow: hidden;
}
.card__media img {
width: 100%;
height: 100%;
object-fit: cover;
}
Prefer aspect-ratio over the old padding-top percentage hack.
HTML attributes still matter
<img
src="/hero.avif"
width="1200"
height="675"
alt="Team at the whiteboard"
decoding="async"
/>
width/height attributes (or CSS aspect-ratio) give the browser an aspect hint for CLS. CSS aspect-ratio on the element is the modern styling approach; attributes remain a good default for content images.
Gallery pattern
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
gap: 0.5rem;
}
.gallery figure {
margin: 0;
aspect-ratio: 1;
}
.gallery img {
width: 100%;
height: 100%;
object-fit: cover;
}
Interview out-loud
“object-fit: cover fills the box and crops; contain shows the whole image. object-position picks the crop anchor. aspect-ratio reserves the box shape to reduce layout shift. I set a real box size, then fit the media inside — fit doesn’t invent height alone without other constraints.”
Footguns
- Applying
object-fitwithout height — nothing to fit into. - Distortion from default
fillon non-matching ratios. - Cropping faces with
cover+object-position: center— tune position. - Ignoring art direction — sometimes
<picture>is better than CSS crop. - Fixed height +
aspect-ratioconflicts — know which wins in the used size calculation.
Video embed wrapper
<div class="video">
<iframe
src="https://www.youtube-nocookie.com/embed/…"
title="Conference talk"
loading="lazy"
allowfullscreen
></iframe>
</div>
.video {
aspect-ratio: 16 / 9;
position: relative;
background: #000;
}
.video iframe {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
border: 0;
}
This pattern reserves space (CLS) and scales cleanly. Same idea for background videos with object-fit: cover on a <video> element filling the box.
Portrait crops for avatars
.avatar {
aspect-ratio: 1;
width: 3rem;
object-fit: cover;
object-position: center 20%; /* bias toward faces */
border-radius: 50%;
}
Background-size comparison
background-size: cover|contain is the background-image cousin of object-fit. Prefer content images when you need alt text; use backgrounds for decorative fills. Do not put meaningful photos only in CSS backgrounds — you lose the accessibility path that img + alt provides. When both appear in a design system, document which component uses which so teams do not mix metaphors.
Related
Further reading
Related guides
- Accent Color and Form ControlsUse accent-color to theme native checkboxes, radios, ranges, and progress — what it paints, what it skips, and when to custom-style instead.
- Auto-fit vs Auto-fillauto-fit collapses empty tracks; auto-fill keeps them. Use both with minmax for responsive card grids without media-query soup.
- BEM Naming MethodologyBlock, Element, Modifier naming for CSS — how it limits specificity wars, what to name, and when utility or CSS modules beat strict BEM.
- blend-mode Basicsmix-blend-mode vs background-blend-mode — how pixels combine, isolation, and the stacking/readability traps in product UI.
- box-sizing border-boxWhy border-box makes width include padding and border, the global reset pattern, and the layout bugs content-box still causes.