<img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=1240251502728721&amp;ev=PageView&amp;noscript=1"> Skip to main content

Tech logs: Use image-set() while supporting Firefox with dynamically loaded background images

The Data Handbook

How to use data to improve your customer journey and get better business outcomes in digital sales. Interviews, use cases, and deep-dives.

Get the book
Author avatar

Thor Galle

Software development

LinkedIn

blog-tech-log-image-set-hero

TL;DR: Firefox can't parse inline style attributes of this form:

<div style="
/* fallback */
background-image: url('fallback-img.jpg');
/* responsive */
background-image: -webkit-image-set(url( ... responsive image set ...));"
>

Solution: put those rules in a <style> tag instead to support fallbacks.


Modern browsers widely support the HTML srcset attribute that enables responsive images (MDN, CanIUse). But for its CSS background-image equivalent image-set() (accessible through -webkit-image-set()), there is no support for IE11, Firefox, Firefox for Android and Opera Mini (MDN, CanIUse). (I'm ignoring IE11 overall).

blog-tech-log-img-set-table

Support of major browsers for image-set() as of February 2021. Source: CanIUse

Of course you'll want to have a non-responsive fallback image for these non-supporting browsers. Well, that's not as obvious as it sounds.

Problem: using style="" doesn't work

You might be tempted to try the following CSS with a fallback url() expression, that gets overwritten with the -webkit-image-set() expression whenever available.

<div style="
/* provide a fallback for Firefox */
background-image: url('../img/image-2x.jpg');
/* override with a responsive image */
background-image: -webkit-image-set(url('../img/image-1x.jpg') 1x, url('../img/image-2x.jpg') 2x);
"
>

Unfortunately, if you add the above code to a style="" attribute (as you would often do when you generate responsive background images somewhere), Firefox 84 will complain with this error in the console:

⚠️ Error in parsing value for 'background-image'. Declaration dropped.

How sad. It dropped the whole style attribute value because it could't load the -webkit-image-set(). As a result, it does also not display the fallback.

Solution: use a <style> tag

The following code works however:

<head>
<style>
.my-image-id {
/* provide a fallback for Firefox */
background-image: url('../img/image-2x.jpg');
/* override with a responsive image */
background-image: -webkit-image-set(url('../img/image-1x.jpg') 1x, url('../img/image-2x.jpg') 2x);
}
</style>
</head>
<body>
<!-- this div should have an image background on it -->
<div class="my-image-id background-box"><div/>
</body>

It seems that a style tag can still be parsed, even though one rule in it is not supported by the browser.

A few things to consider here.

You need a unique class name for each image

The reason you came here in the first place might have been that you wanted to use the style="" attribute, because you were dynamically adding background images to a template using client-side/server-side image data.

In that use case, you now need to perform a few intermediate steps:

  1. Generate a unique class name for the background image set
  2. Add that class to the desired <div> (or other element)
  3. Add a CSS rule for that class to a <style> tag somewhere. This could be a new tag in the <head> OR <body>. It should contain the fallback & responsive background-image URLs for that specific images.

For step 1, you could use a GUID generator. In my project however, I used a JS function to generate valid class names from an alphanumeric image ID string that I got from an API.

Tricky to add style rules to the <head>?
You could add them to the <body> too!

If you were previously trying to add the styles to a style tag, it might be tricky to add styles to a <head>, for example, when coding in a restricted server-side template where you can't access the <head>.

One solution: it's actually possible to add <style> tags to the <body> as well. This is not a good practice since it's non-standard. But it seems to work in most browsers. I tested this in BrowserStack, and so far only UC Browser on Android seemed to have problems with this technique. Here's an adaptation of the previous example with body style tags:

<!-- this div should have an image background on it -->
<div class="my-image-id background-box"><div/>
<style>
.my-image-id {
/* provide a fallback for Firefox */
background-image: url('../img/image-2x.jpg');
/* override with a responsive image */
background-image: -webkit-image-set(url('../img/image-1x.jpg') 1x, url('../img/image-2x.jpg') 2x);
}
</style>

Hope this helped! Feel free to leave a comment if anything is not clear.


Enjoyed the blog? Perhaps you would be interested in working at Columbia Road! We're constantly looking for nice and skilful people to work with – and to have some good banter with! If you are interested in reading more about the work we do at Columbia Road, have a look at our client cases

Join Columbia Road

The Data Handbook

How to use data to improve your customer journey and get better business outcomes in digital sales. Interviews, use cases, and deep-dives.

Get the book