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

Feb 18, 2021 10:15:21 AM

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

Thor Galle

Consultant, Technology

Join Columbia Road

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


Subscribe to our Newsletter

Stay up-to-date what’s going on in digital commerce and Columbia Road. We’ll email you once a month with news, interesting articles and studies from the industry and the crème de la crème of our blog.