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.
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:
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.
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!