Skip to main content

CSS Object-fit and Object-position

object-fit controls how replaced elements like <img> and <video> scale inside their container. object-position sets where that scaled content is positioned within the same space.

Theory

TL;DR

  • Picture a photo frame: cover crops the image to fill the frame; contain shrinks it so you see all of it, with empty space on the sides
  • object-fit handles the sizing strategy; object-position handles alignment (same idea as background-position, but for <img>)
  • Only works on replaced elements (<img>, <video>), not on <div>
  • Default is fill, which stretches the image and distorts aspect ratio
  • Decision rule: hero images use cover; thumbnails use contain

Quick example

css
.card-image { width: 300px; height: 200px; object-fit: cover; /* Scale up, crop overflow */ object-position: center; /* Keep the center of the image visible */ }

A 400x400 square image in this 300x200 box scales up, crops equally from top and bottom, and stays centered. No distortion. This is the core pattern.

Key difference

object-fit picks the scaling strategy: stretch, shrink-to-fit, crop-to-fill, or keep original size. object-position then shifts the result inside the box using coordinates like 50% 30% or keywords like top right. Without explicit object-fit, the browser uses fill by default, which ignores aspect ratio. object-position only has an effect after the fit is applied.

When to use

  • Hero banner, no distortion: object-fit: cover; object-position: center
  • Gallery thumbnails, full image visible: object-fit: contain; object-position: center
  • Profile avatar cropped to face: object-fit: cover; object-position: 50% 30% (eyes near top)
  • Video in letterbox mode: object-fit: contain
  • Logo at original size, no upscale: object-fit: none

Comparison table

ValueScalesAspect ratioCropsFills boxUse when
fillStretches to 100%DistortsNoYesPixel art where distortion is acceptable
containFits fully insidePreservedNo (letterbox)NoThumbnails, full-image previews
coverScales to fillPreservedYes (overflow hidden)YesHero images, cards, avatars
noneNo scalingPreservedPossibleNoLogos, original size matters
scale-downCaps at original sizePreservedNoNoLarge images that should not upscale

Common mistakes

1. Applying object-fit to a <div>

css
/* Wrong: object-fit is ignored on non-replaced elements */ .box { object-fit: cover; background: url(img.jpg); /* Has no effect */ } /* Right: use background-size for divs */ .box { background: url(img.jpg) center / cover no-repeat; }

2. Forgetting width and height on the image

css
/* Wrong: no dimensions, object-fit has nothing to work with */ .container { height: 200px; } img { object-fit: cover; } /* Right */ img { width: 100%; height: 100%; object-fit: cover; }

The image needs explicit dimensions. Without them, it renders at its natural size and object-fit does nothing visible. This is the top reported bug for this property.

3. Portrait image in a landscape box with cover - unexpected side crop

cover crops whichever dimension overflows. A tall portrait in a wide box loses the sides. Fix: object-position: center top to keep heads in frame.

Real-world usage

  • Next.js <Image> with fill layout uses object-fit: cover internally for responsive crops
  • TailwindCSS ships object-cover, object-contain, object-center classes, used across hundreds of thousands of projects
  • Video.js uses object-fit: contain for responsive video embeds
  • For decorative backgrounds on divs, use background-size: cover. object-* is reserved for semantic images with alt text

Follow-up questions

Q: What is the default value of object-fit?
A: fill. It stretches the image to match width and height exactly, which distorts aspect ratio.

Q: How does object-position: bottom differ from object-position: 50% 100%?
A: They are the same. Keywords map to percentages: top = 50% 0%, bottom = 50% 100%, center = 50% 50%.

Q: Does object-fit work on <canvas> or <svg>?
A: On <svg> inserted as a replaced element via <img src="icon.svg">, yes. <canvas> requires manual scaling in JavaScript.

Q: What happens when the browser does not know the image's intrinsic size yet, for example during lazy load?
A: The browser defaults to 300x150px. object-fit computes on that placeholder, then recomputes when the image loads. Without aspect-ratio on the container, you get layout shift. Pair object-fit with aspect-ratio on the wrapper to prevent it.

Examples

Hero banner with cover

css
.hero { width: 100%; height: 500px; overflow: hidden; } .hero img { width: 100%; height: 100%; object-fit: cover; /* Fill without distortion */ object-position: center; /* Center the crop point */ }

The image fills the full width at any viewport size. Whatever the original dimensions are, the browser scales and crops automatically. This is the pattern behind every full-width banner you see.

User avatar with face focus

css
.avatar { width: 80px; height: 80px; border-radius: 50%; overflow: hidden; } .avatar img { width: 100%; height: 100%; object-fit: cover; object-position: center 30%; /* Crop point in upper third - eyes stay in the circle */ }

The 30% from top shifts the crop upward. A face stays centered in the circle instead of showing forehead or chin.

css
.gallery-item { width: 100%; aspect-ratio: 16 / 9; /* Box shape independent of image dimensions */ overflow: hidden; } .gallery-item img { width: 100%; height: 100%; object-fit: cover; object-position: center; transition: transform 0.3s; } .gallery-item:hover img { transform: scale(1.05); }

Pairing aspect-ratio with object-fit: cover removes fixed height values entirely. The box holds its 16:9 shape; the image fills it at any viewport size.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?