CSS Background-Size: Five Examples Explain It

One of the trickier hurdles when leveling up your CSS skills is learning the various options for background-size. There are so many values and value combos to work with that initially it’s even a little intimidating. You’ve got the contain, cover, and auto keywords. Then there are relative units like em and %, and absolute units like px and pt. And then there are all the combinations of relative units, absolute units, and the auto keyword. Instead of going through each possibility one by one, which would be a very long article, I’ve decided to cover five common values/value combinations that each attempt in their own way to solve the most common problem with background images: stretching the background image across its element’s canvas without distorting the image or cutting it in half. Along the way, you will learn how to compare and combine values to achieve 95% of your background-sizing goals.

For the purpose of this article, an element’s canvas is defined as the physical shape on the screen of the element that the background image is applied to, and is represented by the orange-red dashed border in the examples below.

Background-Size: Auto

The default background-size is auto, so it’s the first effect we see when we add the background-image declaration to our CSS, before we even declare the background-size (if we decide to declare it at all). The full value is auto auto, meaning auto width and auto height. You can declare it as simply auto because when a single value is assigned to the background-size property (unless the value is cover or contain), a second value of auto is implied. The first (or only) value is always assigned to the width of the background image, the second (or implied, auto) value is assigned to the height.

That’s how to declare the auto keyword, but what does it do? The answer is, auto automatically calculates the width or the height of a background image based on the length of the opposing dimension (width or height), while maintaining the aspect ratio of the original picture. The aspect ratio is simply the ratio of the width to the height of an element. For example, a rectangle that is 400px wide and 100px tall has an aspect ratio of 4:1.

So to reiterate, if width has a set length, the auto keyword (e.g. background-size: 100px auto) will give the image the image the height it needs to display undistorted. If both width and height are set to auto, the background picture is set to its initial width and height. That’s what we see here:

background-size: auto auto

The image is repeated to fill the canvas (the canvas is represented by the dashed orange-red border). When the image runs out of room, it is cut short. The problem is of course that we don’t want to use a repeating pattern, and we don’t want the image, or in this case images, to be cut off when they reach the edge of the canvas. So we need to move on from background-size: auto.

Background-Size: 100% 100%

Background-size: 100% 100% (100% width and 100% height) solves a couple of the problems we ran into with auto. It fills the element’s entire canvas with a single version of the image, and the image isn’t cropped at all. Of course the downside here is that the background image is distorted when its aspect ratio is different from the aspect ratio of the element’s canvas:

In the situations above, we end up with a stretched out, squished cat. That’s not what we’re after. But we’ve reached an interesting point in our journey. We’ve now found two value combos (Auto auto and auto 100%) that do some of the things we want them to, but not all. It’s time to combine them.

Background-Size: 100% Auto

This gets us a lot closer to our goal. 100% width and automatic height means that the background image is stretched to fill the width of the element’s canvas, and then its height is calculated on the fly (at page load and every time the browser’s viewport is resized), to maintain the original aspect ratio of the background image:

At this point you might be tempted to pack up and call it a day. If the element never changes its aspect ratio this would be fine. But chances are you want the element to change its height and width based on the height and width of the browser’s viewport. That’s where background-size: 100% auto runs into problems. Take a look at background-size: 100% auto when the element maintains same width, but has a taller height:

Now we can see what’s happening more clearly. Background-size: 100% auto leaves a gap at the bottom of the canvas when the element has a taller/skinnier aspect ratio. In the initial example, the element had a shorter/wider aspect ratio compared to the background image, but it wasn’t very noticeable because the image was simply cropped at the bottom (notice kitty’s collar was missing).

We can partly remedy the situation by setting another style rule, background-position, to center, but this will just center the background image vertically in the element’s canvas, leaving a gap above and below the image:

Side Note: If you can imagine, background-size: auto 100% (auto width and 100% height) will do the exact same thing, except that the background image will be expanded to fit the height of the element’s canvas, and then the width will be auto generated, either cutting off the side of the image or leaving white space to the side. Same problem, different perspective.

So background-size: 100% auto is the best value combo we’ve come across so far, but it still isn’t perfect. Our next logical step is to explore background-size‘s two remaining keywords, contain and cover.

Background-Size: Contain

Background-size: contain‘s unique ability is to make the background image, using its original dimensions, as big as possible without ever overflowing the element’s canvas (i.e. keeping it contained). If the image can fill the width of the canvas without the height overflowing, contain will give it a 100% width and auto height. If it can fill the height of the canvas without the width overflowing, contain will give it a 100% height with an auto width. Unless the aspect ratio of the canvas is identical to the aspect ratio of the background image, one and only one of these scenarios (100% auto or auto 100%) will be viable at a time.
Background-size: contain is perhaps easiest to understand with a couple visual examples. Here it is when the element’s canvas is shorter/wider than the background image:
And here it is when the element’s canvas is taller/skinnier than the background image:
The cool thing about contain is that it switches between these two modes on the fly. That is, as the element’s canvas is resized, contain will switch, as necessary, between the two above modes.
The beauty of contain is that it always gives us a complete, undistorted, large as possible background-image. That’s pretty good, when you considered how far we’ve come from background-size: auto. We can’t help it if the aspect ratio of the background image doesn’t match up with the aspect ratio of the element’s canvas, right? So background-image: contain might be as good a solution as any.
Well, there is one more background size value that arguably beats out contain, and that is cover. Let’s look at it next.

Background-Size: Cover

Background-size: cover combines the best of all the options we’ve looked at so far. It essentially does the opposite of contain, by filling either the width or the height of the element’s canvas, whichever causes the image to overflow the canvas on the alternate dimension. So if 100% width makes the image too tall for the canvas, it chooses that option. If instead, 100% height makes the image too wide, it chooses that instead.
The overflowed portion of the picture is cropped out, but we don’t tend to notice, especially with background-position: center center set:
I purposefully used this square shaped element canvas to show just how good background-size: cover is. Here, our rectangular background image has been set to cover a square shaped element canvas. Here, cover is assigning itself 100% height, with the width overflowing on the left and right (with a little help from background-position: center). The image is actually centered on the canvas, the cat’s head in the photograph just happens to be a little left-of-center in the original photo.

This is in my opinion and the opinion of many, as good a solution as any when faced with the problem of placing a background image on an element’s canvas. Especially when the canvas’s shape and size will change with the shape and size of the browser’s viewport. To fully understand how cover works, it was important that we went on the journey we did, seeing how cover uses techniques from 100% and auto sizing, and how it is similar to contain. Now that you’ve learned it, you know exactly how it acts in different situations, which is where you want to be as a CSS developer. You have leveled up in your knowledge of CSS, go forth with renewed confidence.

If you liked (or hated) the article, please leave your comments below. See you next time!

Leave a Reply

Your email address will not be published. Required fields are marked *