2

I've been waiting to use .webp images for a very long time.

It's 2022, so, given:

  • the image format has existed for a decade
  • Chrome started supporting .webp in Jan 2014
  • Firefox started supporting .webp in Jan 2019

I decided the day before yesterday to take the plunge and convert a bunch of .png images on a website to .webp images.

Rookie error. Because, of course, I should have checked: https://caniuse.com/webp first and that would have told me that Safari on anything earlier than macOS 11.0 Big Sur (Nov 2020) does not support .webp images.

But I'm tired of waiting. So... Safari can carry on using .png images I suppose.

Because I absolutely do want to serve .webp images to Firefox, Brave, Chrome, Edge, Opera etc. users.

If I were using marked up images, declaring one or more fallback images is elementary:

<picture>
  <source srcset="a-webp-for-most-browsers.webp" type="image/webp">
  <source srcset="a-png-for-safari.png" type="image/png"> 
  <img src="a-png-for-safari.png" alt="My Image">
</picture>

But (sigh) in this instance, the images are CSS background images, so options for creating fallbacks are more limited:

Am I limited to browser-sniffing via PHP, like this:

if (preg_match('/Mac OS X/', $_SERVER['HTTP_USER_AGENT'])) {

  $Body_Element_CSS_Class_List .= ' oh-no-here-comes-safari';
}

Is there a better / more reliable approach I can adopt than browser-detection?

Rounin
  • 27,134
  • 9
  • 83
  • 108
  • 1
    See one of the answers here that talks about background images: https://stackoverflow.com/questions/58487035/how-to-add-webp-support-in-safari-browser – Rob Feb 11 '22 at 14:04
  • Thanks, @Rob. Which answer do you mean though? VeronicaWatt's answer? I think that answer is out-of-date. – Rounin Feb 11 '22 at 14:16
  • 1
    That's the one but I might have glanced too quickly as I had to leave. – Rob Feb 11 '22 at 15:44
  • @Rob - No worries. To be honest I had to read Veronica's answer 2-3 times before I could completely get my head around it. In any case, I appreciate your taking an interest in the question above. On which note... I think I may have found the solution. I am in the process of testing it now. If everything works I will write it up below. – Rounin Feb 11 '22 at 16:09

2 Answers2

4

I'm having the same issue, but I believe one good way to solve it for CSS background images today would be to use Modernizr.

In that link you can make a Modernizr script build that specifically verifies for webp support in the browser. Then you just have to add the script to the <head> and it'll add classes to the <html> based on the features you're verifying. So, for instance, to load different image formats for a CSS background image you would do:

.webp .image {
  background-image: url('/image.webp');
}
.no-webp .image {
  background-image: url('/image.png');
}
  • In my approach to web development I try to avoid third-party dependencies as much as possible, though I agree this is a viable solution for anyone comfortable with using a third-party dependency like Modernizr. – Rounin May 13 '22 at 11:44
  • 1
    I find this the easiest solution, also because the Modernizr script can be loaded from one's own server, even be pasted into one's own Javascript file that will/should be downloaded in the `head` section. For people who want more information about this method, I'd suggest this article: https://css-tricks.com/using-webp-images/. – Frank Conijn - Support Ukraine May 13 '22 at 11:53
3

Yes, it's hard to provide fallbacks for CSS background-images

In my question I wrote:

If I were using marked-up images, declaring one or more fallback images is elementary [...]

But (sigh) in this instance, the images are CSS background-images, so options for creating fallbacks are more limited

And for now, at least, - ie. while we're still waiting (in 2022) for widespread cross-browser support for the CSS image-set() function - that's true.


But a marked-up <img> can replace each CSS background-image

While I was hunting around for alternative approaches, I unexpectedly came across this July 2021 comment by Quentin Albert:

For what most people use background images for you can nowadays easily use object-fit + object-position.

Source: https://css-tricks.com/using-performant-next-gen-images-in-css-with-image-set/

This was news to me. I was dimly aware of the object-fit CSS property, but I'd never come across the object-position CSS property at all.

But it absolutely works!!


The CSS I would have used if image-set() had support

If image-set() had extensive cross-browser support, this was my intended CSS, which would enable a fallback image for Safari:

.my-image-1 {
  background-image: url(image-set('my-sprited-images.webp', 'my-sprited-images.png'));
  background-position: 0, 0;
}

.my-image-2 {
  background-image: url(image-set('my-sprited-images.webp', 'my-sprited-images.png'));
  background-position: -100px, 0;
}

The HTML + CSS I can use instead (thanks to object-position)

Since the above isn't close to reliable, I can declare the fallback image in HTML instead and position it using object-position:

HTML:

<picture>
  <source srcset="my-sprited-images.webp" type="image/webp">
  <source srcset="my-sprited-images.png" type="image/png"> 
  <img class="my-image-1" src="/my-sprited-images.png" alt="My Image 1">
</picture>


<picture>
  <source srcset="my-sprited-images.webp" type="image/webp">
  <source srcset="my-sprited-images.png" type="image/png"> 
  <img class="my-image-2" src="/my-sprited-images.png" alt="My Image 2">
</picture>

CSS:

.my-image-1 {
  object-position: 0 0;
}

.my-image-2 {
  object-position: -100px 0;
}
Rounin
  • 27,134
  • 9
  • 83
  • 108