Use image-set() while supporting Firefox with dynamically loaded background images
Thor Galle
Posted on November 27, 2020
You don't need to do anything special anymore 🥳 There is full support for image-set
in Firefox since version 89 (released Jun 2021). Go browser standards!
Here's a demo. You'll see it works in Firefox:
The below is an INVALID, old article about a problem that once existed when Firefox didn't support image-set
. Only kept for questionable archival purposes. I will probably unpublish this article later.
<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.
Note: this blog post was a learning from a project at Columbia Road, an updated version can be found on the company site: Tech logs: Use image-set() while supporting Firefox with dynamically loaded background images
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).
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 you need to perform a few intermediate steps:
- Generate a unique class name for the background image set
- Add that class to the desired
<div>
(or other element) - 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.
Posted on November 27, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 27, 2020