A Quick Overview of `object-fit` and `object-position`

object-fit and object-position are my two favourite CSS properties lately. They give developers control over the content inside an img or a video similar to the way that we can manipulate the content of a background with background-position and background-size.

First, let’s dig into object-fit.

This property defines how an element, such as an img, responds to the width and height of its content box. With object-fit we can tell the content to fill that box in a variety of ways such as “preserve that aspect ratio!” or “stretch up and take up as much space as possible!”

Here’s an example:

This image is 400px x 260px. If we style that image like so...

img {  
  width: 200px;
  height: 300px;
}

...then we end up with awkward distortion because that image is being squished to fit that container:

See the Pen 1b15cf30a6226d9f419b4f765458a059 by Robin Rendle (@robinrendle) on CodePen.

The content of our img will take up all the available space inside its new box that we created when we changed its height and width, thus destroying its original aspect ratio.

To preserve the image’s aspect ratio whilst also filling in the space, we can use object-fit:

.cover {
  object-fit: cover;
}

See the Pen 7080df9cb7158c0860b8a66db9667a7d by Robin Rendle (@robinrendle) on CodePen.

The image on the left is our original and the image on the right has cut off the sides of the image, now preserving our aspect ratio! This might not look like a particularly interesting development at this scale but once we move into designing more realistic interfaces then the power of object-fit reveals itself.

Let’s take another example:

See the Pen WrBzey by CSS-Tricks (@css-tricks) on CodePen.

Here we have two images and we want them to fill the width of 50% of the browser window (so they sit side by side) and 100% of the height. This we can do with the help of viewport units:

img {
  height: 100vh;
  width: 50vw;
}

The problem is that when we resize the browser we change the aspect ratio of the images which can cause all sorts of weirdness. Instead, we want to preserve their aspect ratio just like in the previous demo and we can use exactly the same method of doing so. object-fit: cover to the rescue!

See the Pen YwbeoG by CSS-Tricks (@css-tricks) on CodePen.

Try resizing the browser again. No aspect-ratio weirdness, right? This is also extraordinarily helpful if we have images that have different dimensions because they’ll effectively be cropped by their bounding box.

cover is only one of many values for object-fit, more of which you can read about on the Almanac entry, but so far it’s the only value that I’ve found to be the most useful in day-to-day interface development.

Let’s move onto my next favourite thing: object-position.

We’ll get things set up by using the same image as before and using these styles:

img {  
  background: yellow;
  height: 180px;
  object-fit: none;
}

Two things to note here: we need to declare the dimensions for our image in order for object-position to work properly and we also need to set object-fit to none so that the image can be pushed around instead of filling up the whole box, as it would do by default. This makes a bit more sense when you see that the default for object-fit on an image is fill, even if you don’t declare it.

Speaking of defaults, object-position centers all objects horizontally and vertically without a value:

img {
  background: yellow;
  height: 180px;
  object-fit: none;
  object-position: 50% 50%; /* even if we dont declare this the image will still be centered */
}

The first value moves the image left or right and the second moves it up or down. We can experiment with those values here:

See the Pen Object position by Robin Rendle (@robinrendle) on CodePen.

We can even nudge the image inside its content box so that we can reveal the background-color that we set earlier.

But how is this useful? Good question! Well, in a recent project I found that a particular section of an image needed to be moved towards the center so that it caught the attention of the reader. We didn’t need to load a new image, and so we didn’t need the <picture> element in this case, all we wanted to do was move the image over a little bit.

Besides moving the focus of an image, I’m not sure what else this property might be helpful for in a practical sense. But I’ve been messing around with object-position to show how you can hide parts of an image and then reveal bits of it on click, like in this demo:

See the Pen SVG sprite with object-position by Robin Rendle (@robinrendle) on CodePen.

I haven’t experimented with how or why you might use this for <video> elements. Full screen video that hits all the edges, perhaps? There’s plenty more to learn about and explore when it comes to these properties.

What’s the support?

Generally speaking, pretty good!

object-fit is supported by everything except IE/Edge. Whereas, object-position is supported by everything except Safari and IE/Edge.