CSS object-fit and object-position, Explained
object-fit controls how an image or video is cropped inside its box, and object-position controls which part of it stays visible. How they work together.
The object-fit property controls how an image or video is resized to fit its container’s box, and object-position controls which part of that content stays visible when it doesn’t fit exactly. Together they solve a problem CSS struggled with for years: putting a fixed-size image into a fixed-size box without either squashing it or letting it overflow — no wrapper div, no background-image hacks, required.
The problem they solve
Before object-fit, cropping an image to fill a box while preserving its aspect ratio meant either using background-image with background-size: cover (losing the semantics and accessibility of a real <img>) or wrapping the image in a container with overflow: hidden and manually offsetting it with absolute positioning. object-fit lets you keep a real <img> or <video> element, set explicit width and height on it, and control the cropping behavior directly:
img {
width: 300px;
height: 200px;
object-fit: cover;
}
Without object-fit, that same markup would stretch the image to exactly 300×200, distorting its aspect ratio unless the source happened to match.
The five values of object-fit
fill(the default) — stretches the content to fill the box exactly, ignoring its intrinsic aspect ratio. This is the old, distortion-prone behavior.contain— scales the content to fit entirely inside the box, preserving aspect ratio. If the box’s ratio doesn’t match the content’s, you get letterboxing (empty space on two sides).cover— scales the content to fill the entire box, preserving aspect ratio, and crops whatever overflows. This is the most common choice for hero images and thumbnail grids.none— no resizing at all; the content is shown at its natural size, cropped by the box if it’s larger.scale-down— behaves likenoneorcontain, whichever results in a smaller final size.
cover and contain cover the vast majority of real use cases: cover when you want a box always fully filled (like a card grid where every card should look uniform), and contain when you never want to lose any part of the image (like a product photo where cropping might cut off something the customer needs to see).
Where object-position comes in
object-fit: cover decides that cropping happens, but not which part gets cropped away. By default, the content is centered, which is fine for images shot with the subject centered but often wrong for portraits or photos with an off-center focal point. object-position shifts the visible window:
img {
width: 100%;
height: 300px;
object-fit: cover;
object-position: top center;
}
It accepts the same kind of values as background-position: keywords (top, bottom, left, right, center), percentages, or length units, and can be a single value or a pair for horizontal and vertical positioning independently. For a portrait photo cropped into a short, wide box, object-position: top keeps faces from being cut off, which center (the default) frequently does.
Comparison: the five object-fit values
| Value | Preserves aspect ratio | Fills the box | Crops content |
|---|---|---|---|
fill | No (may distort) | Yes | No |
contain | Yes | No (may letterbox) | No |
cover | Yes | Yes | Yes |
none | Yes (natural size) | Only if it happens to match | Yes, if larger than box |
scale-down | Yes | Depends (none or contain) | Only if none applies |
Works on video too
Both properties apply equally to <video> elements, which matters for background-video hero sections or video thumbnails where you want consistent framing regardless of the source video’s native resolution — the same cover/center combination that works for a photo grid works identically for a muted looping video background.
Interaction with responsive images and layout
object-fit doesn’t replace srcset and sizes — they solve different problems. Responsive images (see our guide on srcset and sizes) choose which source file the browser downloads based on viewport and pixel density; object-fit then decides how that downloaded image is cropped inside its box regardless of which source was picked. The two are commonly used together: a srcset picks an appropriately sized file, and object-fit: cover keeps it visually consistent across boxes of different aspect ratios. Setting an explicit aspect-ratio on the same element (covered in our CSS aspect-ratio guide) reserves layout space before the image loads, which prevents cumulative layout shift — pairing it with object-fit gives you a box that never resizes and content that’s always cropped sensibly inside it. If you’re also lazy-loading these images, our lazy loading guide covers keeping that layout stability intact as images enter the viewport.
Format choice matters too: object-fit only changes how a rendered image is displayed on the page, not which format is fastest to download in the first place — see our comparison of WebP, AVIF, and JPEG for that half of the picture. And when the box itself is meant to resize with the container rather than the viewport, pairing object-fit with container queries keeps the cropping sensible at every card width a component might end up rendered at.
The takeaway
object-fit decides how an image or video is scaled to fit its box — stretched, letterboxed, or cropped — and object-position decides which part of the content survives that cropping. cover paired with a non-default object-position handles the overwhelming majority of real layouts: uniform card grids, hero banners, and video backgrounds that need to look intentional regardless of the source file’s original dimensions. Combine both with an explicit aspect-ratio and you get predictable, distortion-free image boxes without a single wrapper div.
Tagged
Keep reading
Takina · · 5 min read CSS inherit, initial, unset & revert Explained
CSS's four global keywords control where a property's value comes from. How inherit, initial, unset, and revert differ, with a comparison table.
Takina · · 4 min read Dynamic Viewport Units: dvh, svh, and lvh Explained
dvh, svh, and lvh fix the classic mobile vh bug where browser toolbars cut off full-height layouts. Here's what each unit measures and when to use it.
Takina · · 4 min read CSS Grid repeat() and minmax() Explained
repeat() and minmax() let CSS Grid build responsive layouts without media queries. How the two functions combine, and common patterns.