What happens when images are broken?

Normally, if you're the good developer that you are, caring about accessibility and your users, alt text will be displayed if one of the images on your site fails to load. If you didn't care then you would forget about the alt text altogether. In the following example I'm writing this: <img src="broken.jpg" alt="Picture of Marco doing a backflip" /> and lo and behold there will be alt text beneath this little paragraph:

Picture of Marco doing a backflip

Be careful, however, when developing for Safari: alt text will only be displayed if you defined a width for the image, and the width needs to be large enough for the text to fit. I worked around this by giving every image 1em of padding on all sides. That did the job in Safari for the example above and the following one, where there's only alt text and nothing else. All the other examples had enough space initially for Safari to display the alt text.

The great thing about alt text is that it is accessible. The icing on the cake is that we can style it. To make it stand out (a little) from the rest of the body copy, we are going to write some CSS:


    img {
      font-family: "Comic Sans MS", cursive;
      font-size: 1.125em;
      color: darkred;
    }
    

Et voilà! Beautifully styled alt text:

Picture of Marco doing a backflip

Options? I love options!

There are more tricky/hacky/nicey things you can do, though. Ire Aderinokun wrote a wonderful article on her blog about why and how it is possible to do some really nice things with your normally miserable and totally unlovable broken images. She also created this Pen.

Pro Tip: that's by far not all there is to her blog. Bookmark it for later, I'll wait for you here. Really, I do.

What groundbreaking thing did Ire present us with there? I'll just quote her to make it easier for all of us and because there's no way I could have said it any better:

Because the element (<img>-element) is controlled by an external source, the ::before and ::after pseudo-elements typically shouldn’t work with it. However, when the image is broken and not loaded, these pseudo-elements can appear.

To me that sounds like awholelottafun! Let's try this!

Styling with ::after

Now, why did I chose ::after to start with? It's because of the wider support across browsers. There's something odd going on in Firefox, where some of the styles applied to the ::before pseudo-element will be applied while others don't, but I'll get to that later.

When having a look at this wonderful table displaying browser support for "CSS Generated Content for pseudo-elements" at caniuse.com, one might think: “Great support across browsers. Yay!” but then you read the "Known issues" and start frowning.

On top of that there is a table on Browser Compatibility regarding this specific technique at Ire's blog. You should have a look at that as well.

Here is an example using ::after with the broken image in order to display additional, hopefully helpful text beneath the alt text. Code first:


    img {
      font-style: italic;
      display: block;
      text-align: center;
      padding: 2.618em;
      color: #000;
      background: #bdbdbd;
    }

    img::after {
      font-size: .875em;
      font-style: normal;
      content: "Oops, seems this one's broken. Sorry. =(";
      display: block;
      margin-top: 1em;
    }
    

The result looks a little bit better than just alt text I think.

Picture of Marco doing a backflip

But beware my fellow front-end development fans! Don't put important messages into the content of a pseudo-element. Why? Accessibility, that's why. Content inside a pseudo-element cannot be accessed with a mouse (like marking, copying and pasting it into Twitter or whatever else you do) and it simply does not exist for assistive technology when using VoiceOver for Mac OS X with Firefox, though it's totally fine with Safari and Chrome. JAWS reads the text inside the pseudo-element and so does NVDA on Windows (with Firefox). Many thanks and a hat-tip to Heydon for helping me clear things up here. If you want to have a poke at it yourself or want to find out what assistive technology with what OS and browser combination does read the text of the pseudo-element and which don't, I suggest you go to this pen by Heydon and give it a go.

tl;dr: You may put important text in your pseudo-elements but VoiceOver for Mac OS X in combination with Firefox (and maybe other untested combinations of assistive technology with a browser of your choice) will not read it out to those users relying on it. Handle with care!

What I also do not want to see in a blogpost with 30+ pictures (all broken) is 30+ times the same fallback image put into place telling me (30+ times in a row) that an image broke while loading. I guess it could make for a great option if you're having only one or two images in your article, though.

Wait a minute! You're suggesting someone might display an image to show that an image broke? Meta, much?

In a way, yes, and here is how you could do it:


    img {
      /** same as before **/
    }
    img::after {
      content: "That's not Marco but just as good.";
      display: block;
      min-height: 240px; /* should match the min-height of the image */
      color: #fff; /* Text-color, if there's some text */
      background: url(fallback.jpg) no-repeat 50% 50%; /* exemplary */
      margin-top: 1em;
    }
    

Result? Sure:

Picture of Marco doing a backflip

OK. So I've proved that it is possible to do this, but whether you should do it is debatable – and please don't do it in the way I did here.

Again but with reason

What would be useful to visitors to your site when confronted with a broken image? Icons. Mostly. I always try to misunderstand them on purpose, which makes them fun again, but icons are a great addition to the alt text. And as we always follow best practices we won't use icon fonts; if they are not supported or not displayed, all you get is a square with gibberish instead of fallback text. What we are going to do is use an SVG instead. Cheers, Sara.

How can we do this? Follow me into the nerdcave:


      img {
        /* again */
      }

      img::after {
        font-style: normal;
        content: "Nothing to see here. Sorry.";
        display: block;
        background: url(broken-image-icon.svg) no-repeat; /* exemplary */
        background-size: 1em 1em; /* matches text-size, scales, lovely */
      }
    

What does it look like now? See here:

Picture of Marco doing a backflip

Alright, this might not be the ideal icon here, but you get the point, right? It's really about giving something visual in addition to the alt text and if you wanted to have a second sentence to excuse your shameful self for having broken images on your site - here you go.

So what's the issue with ::before then?

What I found out building this page is that my beloved Firefox browser displays the alt text inside the ::before pseudo-element by default when an image breaks. That means no matter what I may add as a value to the content attribute in the ::before pseudo-element selector, it will never be displayed in Firefox. “Shenanigans!” you might scream, but I think that's actually a good thing. Who would replace alt text for an image in the first place?

But I am too screaming “Shenanigans!” because of this very weird behaviour. First of all we learned that text inside the ::before and/or ::after pseudo-elements is not accessible: it cannot be marked with the mouse or keyboard and whatnot; and now Firefox is displaying alt text inside one of those?! The result would be inaccessible alt text, right? Wow. What? Why? Anyone? Firefox? Hello! Please! My brain, it hurts.

What else did I learn from writing all of this

It's nice to add a visual enhancement to a broken image and it's very easy to overdo it. While you can up the user experience on your website with this technique, you may want to use it scarcely and unobtrusively.

Also, I learned that my most loved web browser actually fails at a basic accessibility technique – namely displaying alt text of a broken image in a way that assistive technology can access. Bad Firefox! Bad! The other result of this issue is that you shouldn't use the ::before pseudo-element for displaying anything when it comes to broken images because at least one very modern and widely used browser will have issues with this.

Oh! One last thing: if you were hoping to see me doing a backflip, I'm leaving you disappointed. I am not able to do one and I will sure as hell not try to do one because it's hard to get right and it hurts when you're doing it wrong! A lot! Sorry. Google "backflip fail" and you'll see what I mean.

If you read this far: thank you! If you have questions or want to tell me what kind of an idiot I am, there's a link to my Twitter just below.

Lastly, I want to say thanks to Owen Gregory for proofreading this page for me. It means a lot!