[Fix] Background image CSS not working fixes

How to fix background images not appearing in CSS. A common issue is images not loading when we are messing around with relative paths. The post will go over various fixes for that!

Nov 25, 2022 | Read time 11 minutes

🔔 Table of contents

Introduction

One of the frustrating with setting background images in CSS is that the image does not turn up.

So many times something this simple should of been pretty straight forward even when the HTML and CSS seems like it is correct.

In this post, we will go over several ways (or a checklist) on how to fix this type of issue.

How do we use background image?

As the name suggests, the background-image property, sets a background image (or multiple images) for an element.

When you have multiple images, you will need to consider the stacking order. The first image defined will be the top image.

  
  background-image: 
    url(image-one.jpg),
    url(image-two.jpg);
Additionally, when using borders on the element, the border will be on top. Background color will be at the bottom stacking order. This is useful when you use transparent .png images.

Fix 1 - check that the image path is correct

The most likely issue with your background image not working is that the image path that was provided is not correct. Below are a few tips you can go through to check for issues:

👉 Check your relative path

Commonly, the background image is not appearing is because the relative path provided did not resolve.

  • / - This means the root directory
  • ../ - This means going up on directory
  • ./ - This means the current directory
  • ../../ - This means going up two directories

Relative paths depend on the location of the CSS styling. As an example, lets say we include CSS in our HTML file (index.html) like so:

  
<html>
  <style>
    body{
      background-image: url('pictureA.png')
    }
  </style>
  <body>
  </body>
</html>

We also have a bunch of pictures in the following main folder:

  • index.html
  • pictureA.png
  • images/pictureY.png

image of folder structure example

To get pictureA.png, we can use the following command. Notice that since pictureA.png is in the same directory, we can just specify the filename or ./pictureA.png

  
body{
  background-image: url('pictureA.png'); /* or url('./pictureA.png') */
}

To get pictureY.png, since it is located in the images folder, we can use the following command.

  
body{
  background-image: url('images/pictureY.png');
}

As another more complex example, lets say we have the following folder structure with the CSS file as an external file that is referenced by the HTML index.html file.

So our HTML looks something like this:

  
<html>
  <link href="styles/main.css" rel="stylesheet">
  <body>
  </body>
</html>

And the folder structure looks like the following:

  • index.html
  • pictureA.png
  • styles/main.css
  • styles/sample-images/pictureX.png
  • images/pictureY.png

image of folder structure example

Now, since our main.css is in the styles folder, if we want to load pictureA.png then we need to move up one directory level using ../. The code is as follows:

  
body{
  background-image: url('../pictureA.png');
}

Additionally, in this case, since pictureA.png is also in the root folder, the following code will work using /.

  
body{
  background-image: url('/pictureA.png');
}

If we want to acess pictureX.png, then its a matter of going down one level to the sample-images folder.

  
body{
  background-image: url('/sample-images/pictureA.png');
}

If we need to load pictureY.png, then we will need to go up one directory and then down to the images folder like so:

  
body{
  background-image: url('../images/pictureY.png');
}

👉 Using quotes

Earlier versions of CSS and browser implementations, there has been confusion on whether we need quotes or no quotes. According to the official CSS spec, quotes are optional (https://www.w3.org/TR/CSS2/syndata.html#value-def-uri)

So the following code will be the same.

  

body { background-image: url("http://www.example.com/pinkish.png") }

/* Will be the same as the following with no quotes*/
body { background-image: url(http://www.example.com/pinkish.png) }

One exception is that if your image file name contains special characters. In this case, url needs to be URI-escaped (where “(” = %28, “)” = %29, etc.)

👉 Check your image file name and extension

One issue that can trip some people up is that the file names are case insensitive depending on the server that you are hosting the files. With most Unix based servers (Linux, or OSX), the files are case sensitive. While on Windows servers, they are not.

In the example below, lets say we have image called pinkish.png, the second line will not load the image due to the all caps PNG extension

  

body { background-image: url("http://www.example.com/pinkish.png") }

/* Is not the same as the above*/
body { background-image: url(http://www.example.com/pinkish.PNG) }

Additionally for newer extensions such as WebP, browser support common across the latest versions. It will have no or partial support on older browsers. For example Safari 14.0 – 15.6 has full support of WebP, but requires macOS 11 Big Sur or later.

IE 11 or below will have no support for WebP. WebP images displays as a broken image icon in Microsoft Edge v18 in Application Guard mode even when an alternative image source format is available.

👉 Tip: Use absolute paths

While theres benefits of using relative paths for urls() with background-image, my preference would be to use absolute paths.

👉 Tip: Use Live Server in VS Code!

If you are coding with VS Code, then using the Live Server extension is a must. When you are just coding locally without a local server running, references to images can get a bit confusing.

For example, if you use the root directory / - this could mean your actual C:/ root folder instead of the current folder!

Fix 2 - check the height and width of the element

Lets say we have the following div element with class of .card and we want to set the background-image as below:

  
<html>
  <style>
    .card{
      background-image: url('pictureA.png')
    }
  </style>
  <body>
    <div class="card"></div>
  </body>
</html>

In the above case, the div does not have any content so you will not see anything. The div will have a width of 0 and height of 0. To fix this, we need to explictily set the width and height:

  

.card{
  background-image: url('pictureA.png');
  width: 200px;
  height: 200px;
}

Fix 3 - check the syntax is correct

The syntax for creating background images is pretty straight forward. You can apply multiple images to be layted on top of each other. As an example, the below, we have a catfront.png to be under a gradient image.

  
background-image: linear-gradient(
    to bottom,
    rgba(255, 255, 0, 0.5),
    rgba(0, 0, 255, 0.5)
  ), url("catfront.png");

We can also set the background-image using the background shorthand property:

  

/* Using a <bg-image> and <repeat-style> */
background: url("test.jpg") repeat-y;

The background shorthand covers the following CSS properties:

  • background-attachment
  • background-clip
  • background-color
  • background-image
  • background-origin
  • background-position
  • background-repeat
  • background-size

In some instances, when using the shorthand, it would seem like the background-image is not working correctly. This might be due to other properies and not the background image itself.

For example, take the following:

  
background: url("img/background.jpg") cover no-repeat;

This will not work, however if we try to break it down to the explicit CSS properties, it will:

  
background: url("img/background.jpg");
background-size: cover;
background-repeat: no-repeat;

The reason why its not working with the shorthand background property is because we need to specify the position and size as well. So it had nothing to do with our background-image property.

  
background: url("img/background.jpg") 0 0 / cover no-repeat;

Fix 4 - check other styles for overrides

There could be instances where our background image is not working correctly. Consider the following css:

  
.card{
  background: url("img/background.jpg") 0 0 / cover no-repeat;

}

... 
...

.card
background-image: li near-gradient(
    to bottom,
    rgba(255, 255, 0, 0.5),
    rgba(0, 0, 255, 0.5)
  ), url("catfront.png") !important;
}

Now if the catfront.png does not exist, this would mean our card element would not have a background image. The above is not immediately obvious that we are having conflicting background-image set on our card class since we are mixing shorthand vs explicity CSS.

Browser support and bugs

Background-image is generally supported across most browsers so there is not a concern or any weird browser specific hacks or prefixs we need to cater for.

However we should be careful on the type of image we are using. If we are using WebP, Safari 14.0 – 15.6 has full support of WebP, but requires macOS 11 Big Sur or later.

Additionally, there is no support for WebP on IE. As for Edge browsers, WebP images displays as a broken image icon in Microsoft Edge v18 in Application Guard mode even when an alternative image source format is available.

Summary

In this post we went over four possible fixes for when a background-image CSS property is not working. This can be due to using incorrect relative paths, the width and height not being specifified explicitly, incorrect use of the syntax, there are other styles that is overriding the background-image style.

Additionally the type of image format needs to be checked - WebP not supported on older browsers like Safari version 16-15.6, IE 11 or lower.

👋 About the Author

G'day! I am Huy a software engineer based in Australia. I have been creating design-centered software for the last 10 years both professionally and as a passion.

My aim to share what I have learnt with you! (and to help me remember 😅)

Follow along on Twitter , GitHub and YouTube