What CSS object-fit does and why you care

object-fit tells the browser how to resize the contents of a replaced element (usually an <img> or <video>) when the element’s box has a different aspect ratio than the media inside it.

In plain English: it’s how you choose between “crop to fill” (cover), “fit inside” (contain), or “don’t resize” (none) when an image is forced into a fixed-sized frame.

One important gotcha: object-fit does not apply to CSS background images. If you’re styling background-image, you want background-size: cover or background-size: contain instead.

Learn more about CSS backgrounds in the CSS Background Interactive Tutorial.

CSS object-fit property and options

The most common values are cover and contain, but there are a few more that are handy in specific situations.

Object-fit values explained

  • fill (default): stretches the media to match the element’s width and height. This can distort the image.
  • cover: fills the box while preserving aspect ratio. Crops the parts that don’t fit.
  • contain: fits the entire media inside while preserving aspect ratio. Leaves empty space if needed.
  • none: does not resize the media. Uses its intrinsic size.
  • scale-down: picks the smaller result between none and contain.

Interactive object-fit switcher

This playground uses radio buttons to flip the value instantly (and yes, fill is included so you can see the “squish”).

object-fit:
.media {
  object-fit: cover;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  max-width: 980px;
  padding: 18px;
  font-family: system-ui, Arial, sans-serif;
  display: grid;
  gap: 12px;
}

.card {
  border: 3px solid #111;
  border-radius: 18px;
  overflow: hidden;
  background: #fff;
  box-shadow: 0 12px 0 #111;
}

.top {
  height: 220px;
  background: #f6f6f6;
}

.media {
  width: 100%;
  height: 100%;
  display: block;
}

.body {
  padding: 14px;
  display: grid;
  gap: 8px;
}

.body h4 {
  margin: 0;
  font-size: 18px;
}

.body p {
  margin: 0;
  line-height: 1.4;
}
  
Random photo from Picsum

Same frame, different fit

This image is forced into a fixed-height header. Your object-fit choice decides if it crops, letterboxes, stretches, or stays intrinsic.

CSS object-fit: cover

cover is the “make it look good in a card/hero” option. It preserves the image’s aspect ratio and fills the box completely. Anything that doesn’t fit gets cropped away.

If you’ve ever said “I want it to behave like a background image cover, but for an <img>”, this is it.

.thumb img {
  object-fit: cover;
}
  
.thumb img {
  object-fit: cover;
  object-position: 20% 40%;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  max-width: 980px;
  padding: 18px;
  font-family: system-ui, Arial, sans-serif;
  display: grid;
  gap: 12px;
}

.row {
  display: grid;
  gap: 12px;
}

@media (min-width: 820px) {
  .row {
    grid-template-columns: 1fr 1fr;
    align-items: start;
  }
}

.thumb {
  border: 3px solid #111;
  border-radius: 18px;
  overflow: hidden;
  box-shadow: 0 12px 0 #111;
  background: #f6f6f6;
  height: 260px;
}

.thumb img {
  width: 100%;
  height: 100%;
  display: block;
}

.note {
  border: 2px dashed #111;
  border-radius: 14px;
  padding: 12px;
  background: #fff;
}
  

Tip: cover usually pairs with object-position when you want to “aim” the crop.

Portrait-oriented photo from Picsum

With object-fit: cover, the image fills the box. Since the photo is portrait and the frame is landscape, it must crop.

Switch snippets to move the “focus point” using object-position.

CSS object-fit: contain

contain is the “show me the entire image, no cropping” option. It preserves aspect ratio and fits the whole media inside the box.

The trade-off is empty space (often called letterboxing or pillarboxing) when the aspect ratios don’t match. That’s not a bug, that’s the point.

.frame img {
  object-fit: contain;
}
  
.frame img {
  object-fit: contain;
  background: #111;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  max-width: 980px;
  padding: 18px;
  font-family: system-ui, Arial, sans-serif;
  display: grid;
  gap: 12px;
}

.frame {
  width: min(560px, 100%);
  height: 300px;
  border: 3px solid #111;
  border-radius: 18px;
  overflow: hidden;
  background: #f6f6f6;
  box-shadow: 0 12px 0 #111;
  margin: 0;
}

.frame img {
  width: 100%;
  height: 100%;
  display: block;
}

.note {
  border: 2px dashed #111;
  border-radius: 14px;
  padding: 12px;
  background: #fff;
}
  

contain is great for logos, product photos, screenshots, and anything where cropping would be inappropriate.

Wide photo from Picsum

CSS object-position with object-fit

object-position controls which part of the media is shown when the media doesn’t perfectly match the element’s box. It matters most when:

  • You use object-fit: cover (because cropping happens).
  • You use object-fit: none (because the media can overflow and you’re choosing what stays visible).

Object-fit cover position and “center”

When people say “object-fit center”, they usually mean: object-fit: cover plus object-position: center. The default object-position is already 50% 50% (center), but changing it is how you aim the crop.

Interactive object-position sliders

Drag the sliders to move the crop around. This playground edits the two values of object-position (x and y).

.hero img {
  object-fit: cover;
  object-position: 50% 50%;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  max-width: 980px;
  padding: 18px;
  font-family: system-ui, Arial, sans-serif;
  display: grid;
  gap: 12px;
}

.hero {
  border: 3px solid #111;
  border-radius: 18px;
  overflow: hidden;
  box-shadow: 0 12px 0 #111;
  background: #f6f6f6;
  height: 280px;
}

.hero img {
  width: 100%;
  height: 100%;
  display: block;
}

.note {
  border: 2px dashed #111;
  border-radius: 14px;
  padding: 12px;
  background: #fff;
}
  

With cover, changing object-position is like moving a camera window across a big photo.

Tall photo from Picsum

Notice that only Object Position Y has an effect here, because the photo is tall and the frame is wide. The X position doesn’t matter when the media fills the box horizontally.

CSS object-fit not working

When object-fit “does nothing”, it’s almost always one of these issues. Let’s make them visible.

1) The image doesn’t have a real box to fit into

object-fit matters when the element has a constrained size (especially height). If your image is just width: 100% with height: auto, it will keep its natural aspect ratio and there is nothing to “fit”.

2) You’re trying it on the wrong thing

  • Works on: <img>, <video>, and other replaced elements.
  • Does not work on: a regular <div> with background-image. Use background-size there.
.bg {
  background-size: cover;
  background-position: center;
}
  
.bg {
  background-size: contain;
  background-position: center;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  max-width: 980px;
  padding: 18px;
  font-family: system-ui, Arial, sans-serif;
  display: grid;
  gap: 12px;
}

.bg {
  height: 260px;
  border: 3px solid #111;
  border-radius: 18px;
  overflow: hidden;
  box-shadow: 0 12px 0 #111;
  background-color: #f6f6f6;
  background-repeat: no-repeat;
  background-image: url("https://picsum.photos/1200/800");
}
  

This is a background image, so we use background-size, not object-fit.

Quick “make it work” checklist

  • Give the element a constrained box: set both width and height (or use aspect-ratio).
  • Set the media to fill that box: img { width: 100%; height: 100%; }
  • Then apply: object-fit: cover; or contain.
  • If the crop looks “wrong”, adjust: object-position.

Practical patterns you’ll use all the time

Pattern: responsive thumbnail with aspect-ratio

A very clean approach is to define the frame using aspect-ratio, then let the image fill it with object-fit.

.thumb {
  aspect-ratio: 16 / 9;
}

.thumb img {
object-fit: cover;
} 
.thumb {
  aspect-ratio: 1 / 1;
}

.thumb img {
  object-fit: cover;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  max-width: 980px;
  padding: 18px;
  font-family: system-ui, Arial, sans-serif;
  display: grid;
  gap: 12px;
}

.thumb {
  width: min(360px, 100%);
  border: 3px solid #111;
  border-radius: 18px;
  overflow: hidden;
  box-shadow: 0 12px 0 #111;
  background: #f6f6f6;
}

.thumb img {
  width: 100%;
  height: 100%;
  display: block;
}

.note {
  border: 2px dashed #111;
  border-radius: 14px;
  padding: 12px;
  background: #fff;
}
  
Switch snippets to change the frame shape. The image behavior stays consistent.
Random photo from Picsum

Learn more about aspect-ratio in the CSS Aspect Ration Interactive Tutorial.

Pattern: avatar that never distorts

Avatars are the classic “circle crop” case. This is basically cover plus a round frame.

.avatar img {
  object-fit: cover;
  object-position: center;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  max-width: 980px;
  padding: 18px;
  font-family: system-ui, Arial, sans-serif;
  display: grid;
  gap: 12px;
}

.row {
  display: flex;
  gap: 12px;
  align-items: center;
}

.avatar {
  width: 96px;
  height: 96px;
  border: 3px solid #111;
  border-radius: 999px;
  overflow: hidden;
  background: #f6f6f6;
  box-shadow: 0 10px 0 #111;
  flex: 0 0 auto;
}

.avatar img {
  width: 100%;
  height: 100%;
  display: block;
}

.card {
  border: 3px solid #111;
  border-radius: 18px;
  padding: 12px 14px;
  background: #fff;
  display: grid;
  gap: 6px;
  width: min(520px, 100%);
}

.card h4 {
  margin: 0;
  font-size: 16px;
}

.card p {
  margin: 0;
  line-height: 1.4;
}
  
Portrait photo from Picsum used as an avatar

Avatar crop

object-fit: cover keeps faces from becoming pancakes.

Wrap-up: the object-fit mental model

Remember the simple recipe:

  1. Make a frame (set height or aspect-ratio).
  2. Make the media fill the frame (width: 100% and height: 100%).
  3. Choose the behavior: cover to fill and crop, contain to fit and letterbox.
  4. If the crop needs aiming, tweak object-position (often “center” or a percentage).