Reference guide · images · Published 2026-08-16 · 4 min read

CSS object-fit and object-position for images

CSS object-fit cover, contain, fill, none and scale-down explained with object-position, aspect-ratio pairing and the CLS pitfalls to avoid.

What object-fit does

object-fit tells the browser how to display an image inside its content box: cover, contain, fill, none, and scale-down. The image element keeps its layout size (the box from width/height/aspect-ratio) and object-fit decides what part of the image renders into that box.

ValueBehaviourCommon use
coverScale the image to fill the box; crop overflow so no box is emptyCard thumbs, hero, avatar, gallery tile
containScale to fit entirely inside the box, possibly leaving letterbox spaceProduct shots where nothing may be cut
fillStretch/squash the image to the exact box sizeThe old default; distorts at odd ratios
noneIgnore scaling; render at the image's natural size, clip the boxMood pieces at natural detail
scale-downEquivalent of none or contain, whichever is smallerIcons/logos

An <img> with object-fit: contain does not re-layout the page; it only paints a smaller version inside the box, which is what the aspect-ratio article complements with the opposite technique (matching the box to the source).

Cropping with cover and object-position

The crop point defaults to the center. object-position moves it:

.thumb { object-fit: cover; object-position: 50% 20%; }

Percentages are positions in the box, not margins: 0% 0% is the top-left, 100% 100% the bottom-right, 50% 20% near the top center. Lining up a portrait face or a logo in the top-left of every card is the classic use. The background-position pairing article covers the background sibling for CSS backgrounds, which is the same positioned-crop concept on a different plate.

The cover vs contain trade-off

For a card with a fixed box, cover guarantees the box is full (no letterbox) at the cost of cropping; contain guarantees the entire image is visible at the cost of empty space. The choice is aesthetic unless the image is a screenshot or portrait where part of it matters: then contain is the honest answer and cover crops data, not just pixels.

The aspect-ratio pairing

object-fit sits well with a fixed aspect ratio so the box does not change with the source:

.card img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

The aspect-ratio property reserves the height before the image loads. That removes the layout shift a tall/short image would otherwise cause when it pops in and the browser reflows the text below, which is exactly the CLS the metric punishes.

The shift trap

If you skip aspect-ratio and the source files differ in ratio, the box height jumps when each image loads: the classic card mesh that visibly rearranges. The two-part fix is always:

  1. Reserve the space: aspect-ratio (or fixed height) on the element.
  2. Fill it gracefully: object-fit: cover so a wide and a tall image both fill the same box.

Where the exact intrinsic width is the old story, the srcset candidates should include a file close to the rendered width, and sizes matched to the box, so cover crops from a sensible source rather than from a scaled-down master (explained in the picker article).

When background is better

background-image with background-size: cover and background-position: center gives the same crop for decorative images, but none of the accessibility or SEO value of an img with alt. Choose img + object-fit for meaningful content, and background only for texture that never carries meaning. The background LCP article covers how background images cannot be preloaded and load late, which is a real LCP cost when one fills the hero.

Need a website built, fixed, optimised, migrated or replaced?

This technical resource is written by CSMBAC, a small design and development studio. If you would rather hand the problem to a professional, the website service page explains how we build enquiry-ready websites.

Explore website services