16

Okay, let's say you have something like this:

<span class="image" style="background-image: url('http://www.example.com/images/image1.png')"></span>

Every CSS tutorial I've ever read has covered the concept of using a background color after the background-image code, which of course takes the place of the image when one is unavailable, but...

How do you specify a backup background-image - one that should be displayed if the image referenced is unavailable? If there's no CSS trick for this, maybe JavaScript could handle it?

tylerl
  • 1,160
  • 1
  • 19
  • 41
  • 2
    Are you actually trying to do this, or is the question just academic? If your images are failing when they aren't supposed to it seems like there's a good chance your plan b image will fail too. Seems very impractical to me. – Syntax Error Oct 19 '11 at 05:45
  • 1
    In my opinion, even if you _can_ do this, you shouldn't. It means an extra HTTP request, and could potentially hide a file-system organization problem. – Nightfirecat Oct 19 '11 at 05:51
  • @SyntaxError, if the url is dynamic as with Angular, you may not know if the image exists, as in icons that represent file extensions. – toddmo Nov 04 '15 at 16:13
  • @toddmo I don't use Angular, but if you're generating dynamic urls in any language you probably shouldn't be generating anything that's going to 404 and crap up your logs. It's an error response for a reason - it means you're doing something wrong. The test and fallback should be in your dynamic code of whatever language you're using to prevent generating urls that go nowhere. – Syntax Error Nov 09 '15 at 18:43
  • @SyntaxError, so sidonaldson's answer will generate 404s. I guess so b/c it tries the first one and the only way it knows the image is bad is to get a 404, correct? – toddmo Nov 09 '15 at 18:53
  • I'm not 100% about chaining images in CSS like that, but I expect it would have to generate a 404 when requesting the image to see if it's there. – Syntax Error Nov 09 '15 at 19:42

4 Answers4

32

In modern browsers you can chain background images and have more than one on each node. You can even chain background-position and background-repeat etc! This means you can declare your first image (which is the fallback) and then the second one appears over it, if it exists.

background-color: black;
background-image: url("https://via.placeholder.com/300x300?text=Top Image"), url("https://via.placeholder.com/300x300?text=Failed To Load");
background-position: 0 0, 0 0;
background-repeat: no-repeat, no-repeat;

JFIDDLE DEMO

sidonaldson
  • 24,431
  • 10
  • 56
  • 61
  • 5
    Only problem with this is if there is transparency in the default image. The fallback image will be partially visible if there is any transparency. – Stewart Jun 03 '16 at 16:35
  • 1
    For me it works perfectly in Chrome and Firefox. Exactly what I was looking for. Somehow `background: url(img1.png), url(img2.png);` did not work. – Zlelik Jul 05 '16 at 15:09
  • @Zlelik that's right, it has to be `background-image` as `background` is shorthand for all the properties – sidonaldson Jul 05 '16 at 15:29
8

Simple answer:

You could either nest the span inside another span - with the outer span set to use the backup background image. If the inside span's background isn't available, then you'll see the outside one's

Better, more difficult answer:

You could achieve a similar result in pure CSS, by adding some psuedo content before the span, and then styling that to have the fallback background. However, this usually takes some trial and error to get it right;

Something lile

span.image:before{content:" "; background:url(backup.png); display: block; position:absolute;}
Community
  • 1
  • 1
Matt Tew
  • 1,581
  • 1
  • 9
  • 15
  • I ended up just doing the onerror thing and fixing the styling issue I had from switching to an from a . Thanks a lot though, this is a great thing to know for the future :) – tylerl Oct 20 '11 at 03:04
  • 2nd solution doesnt work – vazun Nov 26 '22 at 10:28
0

Well, I know that the actual tag has onload, onerror, and onabort events. You could try loading it in an image, then if that succeeds, use JS to set the background property of the body.

EDIT: Never mind. I like his answer better.

BinderNews
  • 570
  • 3
  • 10
0

Just declare the preferred default image after your background declaration:

.image
{
    background: #000 url('http://www.example.com/images/image1.png') 0 0 no-repeat;
    width: xxpx;
    height: xxpx;
    background-image: url('http://www.example.com/images/image1.png');
}

<span class="image"></span>

idk the dimensions of your img, so they are "xxpx" working demo: http://jsfiddle.net/jalbertbowdenii/rJWwW/1/

Dan Hlavenka
  • 3,697
  • 8
  • 42
  • 60
albert
  • 8,112
  • 3
  • 47
  • 63