🖼 Cross browser solution for styling broken images 🔨

You may have seen some web pages with broken images. It diminishes website trustworthiness and it just looks bad. Let’s explore some solutions to broken images and have a reliable fallback in all browsers.

Intro

This is how our problem looks like. Note that this line of copy (next to the image icon) comes from the alt property of the <img> tag.

See the Pen WLzgpN by Anatoli (@makaroni4) on CodePen.

Common solution

The most popular solution atm is to use :before/:after pseudo elements. Idea is that we position pseudo element absolutely over the image and fill it with color/gradient. Here’s a CSS snippet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
.img {
  /* Otherwise pseudo element will fill
  in the whole page (because of width: 100%) */
  position: relative;
}

&:before {
  width: 100%; /* Make sure we fill in the whole image area */
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  display: flex;
  /* We want to center copy from alt tag horizontally & vertically */
  align-items: center;
  justify-content: center;

  /* Nice gradient from https://cssgradient.io */
  background: linear-gradient(to right, #fa709a 0%, #fee140 100%);

  color: #FFF;
  font-size: 16px;
  font-weight: bold;
  font-family: 'Varela Round', sans-serif;

  /* Cool trick: we're using CSS attr() function to retrieve alt property copy */
  content: attr(alt);
}

This is a live example of this approach:

See the Pen Broken image styling with :before pseudo element by Anatoli (@makaroni4) on CodePen.

It’s very elegant, CSS-only. It has a major drawback though – it doesn’t work in Safari (neither on desktop nor on mobile) ⚠️ For example, this blog has about 30% of visits from Safari. It is simply unacceptable.

JS solution

It’s quite hard to think of a pure CSS solution which would be 100% cross browser. Let’s use onerror event handler which is supported by all browsers. We’ll simply replace broken image tag with a div of the same size, fill it with gradient and use alt tag’s content. IMO it’s the best way because it keeps our <img> tags untouched (so we don’t need to extra markup manually). Here’s a JS snippet with the solution:

1
2
3
4
5
6
7
8
9
10
11
12
13
document.querySelector(".img").onerror = function() {
  const img = this;

  img.style.display = "none";

  const imgFallback = document.createElement("div");
  imgFallback.className = "img-fallback";
  imgFallback.innerHTML = img.alt;
  imgFallback.style.width = img.width ? img.width + "px" : "300px";
  imgFallback.style.height = img.height ? img.height + "px" : "300px";

  img.parentNode.insertBefore(imgFallback, img.nextSibling);
}

Here it is in action:

See the Pen Styling broken image with JS by Anatoli (@makaroni4) on CodePen.

Note, that we still use some CSS to style a fallback <div> block (we gave it a class img-fallback):

1
2
3
4
5
6
7
8
9
10
11
12
.img-fallback {
  display: flex;
  align-items: center;
  justify-content: center;

  background: linear-gradient(120deg, #f093fb 0%, #f5576c 100%);

  color: #FFF;
  font-size: 16px;
  font-weight: bold;
  font-family: 'Varela Round', sans-serif;
}

Let’s sum up. We have ~20 LOC no-external-dependencies solution to keep your website free from broken images. Not so bad, right? 🍻

P.S. If you know a better way to handle broken images – let everyone know in comments.

“no fuss, just things you actually need”

Start learning with SQL Habit today

Master Data Analysis with SQL through the story of how a startup succeeded through data.
TRY 35 LESSONS FOR FREE

Explore other articles

2019

2018

2017

2014

2012