The CSS background-image property as an anti-pattern
Tags: css, images, frontend
Published: 2020-02-25 21:19:12

---
title: The CSS background-image property as an anti-pattern
published: true
date: 2019-05-28 12:49:00 UTC
tags: css,images,frontend
canonical_url: https://nystudio107.com/blog/the-css-background-image-property-as-an-anti-pattern
---

# The CSS background-image property as an anti-pattern

### The CSS back­ground-image prop­er­ty allowed us to do some amaz­ing things, but in most cas­es, it’s time to leave it behind.

Andrew Welch / [nystudio107](https://nystudio107.com)

![Css background image](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_1200x675_crop_center-center_82_line/css-background-image.jpg)

Many of us have cut our teeth using the CSS [back­ground-image prop­er­ty](https://developer.mozilla.org/en-US/docs/Web/CSS/background-image) to do a wide vari­ety of things. To many, it’s like an old friend, but it’s one we should con­sid­er say­ing good­bye to.

The real prob­lem isn’t the CSS <kbd>background-image</kbd> prop­er­ty itself. Rather it is that it’s been used in places where it real­ly should­n’t be, such as for the main CTA hero image or for UI images.

Used improp­er­ly, <kbd>background-image</kbd> can be an anti-pat­tern. Are there legit use cas­es for <kbd>background-image</kbd>? Of course.

How­ev­er, there are some seri­ous down­sides to using the CSS <kbd>background-image</kbd> prop­er­ty, and more impor­tant­ly, we have bet­ter ways to imple­ment images in our browsers today.

<aside>
                                Let us not speak of the days of danc­ing ham­ster backgrounds
                            </aside>

So let’s jump right in and talk about the down­sides of using the CSS <kbd>background-image</kbd> prop­er­ty, and then what we can use instead.

![Bad boy doggo](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_1200x675_crop_center-center_82_line/bad-boy-doggo.jpg)

Here are a few rea­sons why using the CSS <kbd>background-image</kbd> prop­er­ty can be bad:

## 1. Bad for SEO

Images that are in CSS <kbd>background-image</kbd> prop­er­ties are not crawled or indexed by Google. No big deal right? Well, check out this quote from the [How to Rank in Google Image Search](https://moz.com/blog/seo-photos-visuals-graphics-whiteboard-friday) Moz​.com article:

<aside>
                                …a third of all search­es per­formed in Google are for images and <span>12</span>.<span>5</span>% of SERPs show Image Pack results…
                            </aside>

Let that sink in. One third or 33% of search­es per­formed in Google are for images. If the image is rel­e­vant at all to the sub­ject of the page, or your clien­t’s busi­ness (and if its not, it prob­a­bly should be), you absolute­ly want to be indexed.

If you use <kbd>background-image</kbd> you miss out on this, nor can you have an <kbd>alt=""</kbd> descrip­tion of the image to give Google a descrip­tion & con­text for the image.

## 2. Bad for Accessibility

The CSS <kbd>background-image</kbd> prop­er­ty is not good for acces­si­bil­i­ty. [Screen read­ers](https://www.boia.org/blog/why-screen-readers-are-essential-for-website-accessibility) will ignore <kbd>background-image</kbd> entirely.

Have a look at the [Acces­si­bil­i­ty Con­cerns](https://developer.mozilla.org/en-US/docs/Web/CSS/background-image#Accessibility_concerns):

<aside>
                                Browsers do not pro­vide any spe­cial infor­ma­tion on back­ground images to assis­tive tech­nol­o­gy. This is impor­tant pri­mar­i­ly for screen read­ers, as a screen read­er will not announce its pres­ence and there­fore con­vey noth­ing to its users.
                            </aside>

Even if screen read­ers did­n’t com­plete­ly ignore images, there’s no <kbd>alt=""</kbd> text that can give a use­ful descrip­tion of the image or con­text for it.

**Pro Tip:** If you actu­al­ly _want_ a screen read­er to skip an image (maybe it’s just a design ele­ment), just have an emp­ty alt tag, e.g.: <kbd>alt=""</kbd> (the use of the <kbd>role="presentation"</kbd> prop­er­ty is not opti­mal, as it vio­lates the [first rule of ARIA](https://www.w3.org/TR/using-aria/#rule1)).

## 3. Bad for Performance

How could the <kbd>background-image</kbd> prop­er­ty pos­si­bly be bad for per­for­mance? Because typ­i­cal­ly just one image is used for the <kbd>background-image</kbd> prop­er­ty regard­less of the device screen width or resolution.

What we ide­al­ly want is to be able to use [respon­sive images](https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images) so that the brows­er can load a dif­fer­ent sized image depend­ing on the device’s screen width or resolution.

This makes a mas­sive dif­fer­ence on mobile device or low band­width con­nec­tions, as well as on the pro­cess­ing pow­er need­ed to scale images. [Check out the Post-Mortem: Applied Image Opti­miza­tion](https://dev.to/gaijinity/post-mortem-applied-image-optimization-fge-temp-slug-3708162) arti­cle for details.

<aside>
                                On a typ­i­cal site, images will by far be the largest chunk of the data sent. We should opti­mize them.
                            </aside>

While you can do this via <kbd>@media</kbd> queries with CSS <kbd>background-image</kbd> it ends up get­ting real­ly sticky if you need to change the image or rename it or ver­sion it.

The rea­son it gets sticky is that the image is embed­ded in your CSS, which is typ­i­cal­ly built by a build process that is not in the clien­t’s control.

So because it’s hard, peo­ple usu­al­ly just punt on it and have one ver­sion of the image for all device screen sizes and resolutions.

While there are JavaScript libraries such [bgset](https://github.com/aFarkas/lazysizes/tree/gh-pages/plugins/bgset) to help out, why add yet more JavaScript to solve a prob­lem that has so many oth­er downsides?

Add in the desire to use next-gen­er­a­tion forms like [webp](https://developers.google.com/speed/webp/) as a pro­gres­sive enhance­ment, and things get real­ly icky with <kbd>background-image</kbd>.

<aside>
                                Your brows­er can’t start down­load­ing an image until it has down­loaded <span>&amp;</span> parsed the <span>CSS</span>
                            </aside>

Anoth­er per­for­mance ben­e­fit is that if your images are embed­ded in your CSS via <kbd>background-image</kbd>, the brows­er has to down­load and parse your CSS before it can request the images.

This means your hero image is going to be low­er down the down­load queue, and slow­er to load. If you do your images via HTML ele­ments instead, the brows­er can request them much faster, some­times even before the stylesheets start downloading.

## 4. Bad for CMS’s & CDN’s

The CSS <kbd>background-image</kbd> prop­er­ty is also not great when it comes to [Con­tent Man­age­ment Sys­tems](https://craftcms.com/) and [Con­tent Dis­tri­b­u­tion Net­works](https://www.cloudflare.com/learning/cdn/what-is-a-cdn/) (CDNs).

Let’s say that I have a hero image on my web­site that I imple­ment­ed as a <kbd>&lt;div&gt;</kbd> with the image set via <kbd>background-image</kbd> and then my web­site takes off!

Peo­ple from all over the world are hit­ting my site, and I want to use a CDN to deliv­er these resources to them optimally.

If I have the image URL embed­ded in my CSS, I’m going to have to do a glob­al search and replace for all of my images to switch over their URLs from local URLs to my CDN URLs.

If you pref­aced all of your image URLs with [CSS vari­ables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties), good for you! But most peo­ple don’t, and hav­ing to build and deploy a new CSS asset bun­dle when­ev­er you want to change your images seems… exces­sive. But it’s either that, or dynam­i­cal­ly gen­er­at­ing inline CSS… but let’s not go there.

It’s be much eas­i­er to just let your CMS han­dle the URL pre­fix, but that can get gross if you’re doing it via CSS <kbd>background-image</kbd>, neces­si­tat­ing the gen­er­a­tion of inline styles and oth­er shenanigans.

Putting image URLs in CSS always feels like ​“hard­cod­ing it” to me now.

## So when is it good?

So we’ve been talk­ing all about the down­sides, but when is it actu­al­ly good to use the CSS <kbd>background-image</kbd> property?

![Good boy doggo](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_1200x675_crop_center-center_82_line/good-boy-doggo.jpg)

It may seem bla­tant­ly obvi­ous, but if you have the case where you actu­al­ly have an image as a pure­ly [dec­o­ra­tive image](https://www.w3.org/WAI/tutorials/images/decorative/) back­ground… that’s when to use <kbd>background-image</kbd>!

<aside>
                                It’s good to use back­ground-image when you have an actu­al back­ground image
                            </aside>

If you are doing that, con­sid­er using [image-set()](https://developer.mozilla.org/en-US/docs/Web/CSS/image-set) along with <kbd>background-image</kbd> to mit­i­gate the per­for­mance issues men­tioned above.

It’s not that the prop­er­ty is inher­ent­ly bad, it’s that it has been shoe­horned into doing things it prob­a­bly isn’t the best choice for.

## Use <pic­ture> instead!

I think a large rea­son peo­ple use <kbd>background-image</kbd> is because of the CSS <kbd>background-size: cover;</kbd> prop­er­ty. It lets you make sure that an image ​“cov­ers” the thing its attached to in an aes­thet­i­cal­ly pleas­ing way. 

<aside>
                                The object-fit prop­er­ty is here to save the day!
                            </aside>

If you use the seman­tic HTML ele­ment <kbd>&lt;picture&gt;</kbd> with the [object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) prop­er­ty you get the same ben­e­fits of <kbd>background-size: cover;</kbd> but you also get:

- SEO-friend­ly images
- Acces­si­bil­i­ty friend­ly images (just use the <kbd>alt=""</kbd> property)
- Works great with CMS-gen­er­at­ed image links & CDNs
- Works great with [src­set](https://cloudfour.com/thinks/responsive-images-101-part-4-srcset-width-descriptors/) for opti­mized images
- Can use <kbd>&lt;source&gt;</kbd> for next-gen­er­a­tion image for­mats like <kbd>.webp</kbd>

It’s real­ly not hard to do, and the ben­e­fits are numer­ous! The <kbd>object-fit</kbd> prop­er­ty tells the image or video how it should fit into the par­ent con­tain­er. You’d just change this:

```

<div style="background-image: url('/some/man-with-a-dog.jpg');
            background-size: cover;">
</div>

```

To this:

```

<picture>
  <img src="/some/man-with-a-dog.jpg"
       alt="Man with a dog"
       style="object-fit: cover;"
  />
</picture>

```

Obvi­ous­ly in both cas­es, you prob­a­bly would­n’t be using inline styles, but hope­ful­ly you can see how much more flex­i­ble of an approach we have if we ditch the <kbd>background-image</kbd> prop­er­ty and use actu­al seman­tic HTML ele­ments like <kbd>&lt;picture&gt;</kbd> and <kbd>&lt;img&gt;</kbd>.

We can then eas­i­ly add respon­sive­ly sized images via <kbd>srcset</kbd>. We can also eas­i­ly add a next gen­er­a­tion image for­mats like <kbd>.webp</kbd> for the brows­er to choose from via <kbd>&lt;source&gt;</kbd> as well.

Then we also get to take advan­tage of things like [native image lazy load­ing](https://addyosmani.com/blog/lazy-loading/) in Chrome and oth­er browsers as it gets implemented.

Here’s what an final block of code that does all the things might look like:

```

<picture>
    <source
        srcset="/some/_1170x658_crop_center-center/man-with-a-dog.webp 1170w,
                /some/_970x545_crop_center-center/man-with-a-dog.webp 970w,
                /some/_750x562_crop_center-center/man-with-a-dog.webp 750w,
                /some/_320x240_crop_center-center/man-with-a-dog.webp 320w"
        sizes="100vw"
        type="image/webp"
    />
    <source
        srcset="/some/_1170x658_crop_center-center/man-with-a-dog.jpg 1170w,
                /some/_970x545_crop_center-center/man-with-a-dog.jpg 970w,
                /some/_750x562_crop_center-center/man-with-a-dog.jpg 750w,
                /some/_320x240_crop_center-center/man-with-a-dog.jpg 320w"
        sizes="100vw"
    />
    <img
        src="/some/man-with-a-dog-placeholder.jpg"
        alt="Man with a dog"
        style="object-fit: cover;"
        loading="lazy"
    />
</picture>

```

This gives us

- [lazy load­ing](https://addyosmani.com/blog/lazy-loading/) if the brows­er sup­ports it (oth­er­wise it does nothing)
- <kbd>webp</kbd> if the brows­er sup­ports it (oth­er­wise it does nothing)
- a <kbd>srcset</kbd> of opti­mized respon­sive images that the brows­er can choose from.

SEO friend­ly, pro­gres­sive enhance­ment, acces­si­bil­i­ty and per­for­mance all rolled up into one nice tight lit­tle bundle.

![Tight little bundle seo performance accesibility](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_1200x675_crop_center-center_82_line/2825/tight-little-bundle-seo-performance-accesibility.jpg)

Boom. 💥

And all of the images can be com­ing auto­mat­i­cal­ly sized from our CMS via tools like [Ima­geOp­ti­mize](https://nystudio107.com/plugins/imageoptimize), mak­ing it easy to point to a CDN or Ama­zon S3. Final­ly, you can do some very cre­ative [crop­ping of images](https://alligator.io/css/cropping-images-object-fit/) with <kbd>object-fit</kbd>.

## Out with the old, in with the new

[Brows­er sup­port](https://caniuse.com/#search=picture) for <kbd>&lt;picture&gt;</kbd> and <kbd>srcset</kbd> is pret­ty fan­tas­tic (with a [poly­fill](https://scottjehl.github.io/picturefill/) if you need it), and so is [brows­er sup­port](https://caniuse.com/#feat=object-fit) for <kbd>object-fit</kbd> (also with a [poly­fill](https://github.com/bfred-it/object-fit-images) if you need it). Anoth­er nice pat­tern to use is this via [poly​fill​.io](https://polyfill.io)

So the time is now to ditch <kbd>background-image</kbd> from your toolset (except in the rare cas­es where you actu­al­ly want a back­ground image).

![Out with the old in with the new](https://nystudio107-ems2qegf7x6qiqq.netdna-ssl.com/img/blog/_1200x675_crop_center-center_82_line/out-with-the-old-in-with-the-new.jpg)

Code using best prac­tices for the over­whelm­ing major­i­ty now, then use pro­gres­sive enhance­ment and a poly­fill when nec­es­sary. Don’t be shack­led to the past for what amounts to a very small per­cent­age of your visitors.

<aside>
                                Don’t use a con­tent image as dec­o­ra­tion; use seman­tic <span>HTML</span> con­tent image elements
                            </aside>

I think you’ll find that you end up build­ing web­sites that are more SEO friend­ly, more acces­si­ble, and more per­for­mant… as well as just feel­ing more sat­is­fy­ing to write in a seman­tic HTML way.

The CSS <kbd>background-image</kbd> prop­er­ty was nev­er meant to be used for your hero images or UI ele­ments. So now that bet­ter ways to do it are here, let’s use ​‘em.

If this is got­ten you excit­ed about opti­miz­ing images, check out the excel­lent [images.guide](https://images.guide/) for a com­pre­hen­sive write up.

Enjoy your <kbd>object-fit</kbd>!

## Further Reading

_If you want to be notified about new articles, follow [nystudio107](https://twitter.com/nystudio107) on Twitter._

<small>Copyright ©2020 nystudio107. Designed by nystudio107</small>