Question

My end goal is to detect if the browser is capable of displaying webp images. If it is, replace all the images on the page with their webp equivalent (located in the same directory with the same name, just different extension)

Currently I have a script that successfully detects if the browser is able to display webp

(function(){
  var WebP=new Image();
  WebP.onload=WebP.onerror=function(){
    if(WebP.height!=2){
      console.log("You do not have WebP support.");
    } else {
      console.log("You do have WebP support.");
    }
};
  WebP.src='data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
        })();

Inside the case for having webp support I have tried the following code but been unsuccessful.

// replace .gif with .webp
var allImages = document.body.getElementsByTagName("img");
var length = allImages.length;
var i;
for(i = 0; i < length; i++){
  allImages[i].src.replace("png", "testtest");
  console.log(allImages[i]);
}

When placed in the header the console does correctly show all of the image tags, but the source has not been changed from the filename.png that it originally was.

Any ideas on what is being done incorrectly?

Edit: I found found out the problem with why it was not loading the images, thanks to wsanville. Looking at the network tab in chrome however still reveals that I am loading both the png and now the webp image as well. How can I prevent the png image from loading in the first place?

Was it helpful?

Solution

The replace function returns a string, it doesn't mutate it. You just need to assign the value back:

allImages[i].src = allImages[i].src.replace("old", "new")

Edited for comment: All browsers will download the corresponding file in the src attribute of an image. As an alternate to your approach, I suggest storing the file name in a different attribute of the img tag.

Your image tags could look like:

<img alt="" data-png-source="/path/to/image.png" />

The corresponding Javascript could set the src attribute to the correct version.

var supportsWebP = true; //set this variable properly

for(i = 0; i < length; i++)
{
    var image = allImages[i];
    var pngSource = image.getAttribute('data-png-source');
    image.src = supportsWebP ? pngSource.replace('.png', '.webp') : pngSource;
}

OTHER TIPS

I know this a very old question, but as I looked for a way to replace webp images with corresponding jpgs, I didn't find much.

With this post, I put this together which seems to work through IE 9.

(It might actually work further back with an older jQuery version, but I'm using jQuery 2.1.1 which breaks in IE <= 8 so I'm not certain)

It checks for .webp support, then if the browser doesn't support .webp, it replaces all occurrences with a .jpg equivalent.

$(function() {
  var WebP=new Image();
  WebP.onload=WebP.onerror=function(){
    if(WebP.height!=2){
      $('img[src$=".webp"]').each(function(index,element) {
        element.src = element.src.replace('.webp','.jpg');
      });
    }
  };
  WebP.src='data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
});

If you have (some) control of the server, you can use content negotiation instead of javascript. See http://httpd.apache.org/docs/2.2/content-negotiation.html for how it's done in Apache.

You are actually trying to solve a variation of the classic responsive image problem.

The problem you have with changing the image src attributes is that a modern browser will look ahead and start downloading images with the wrong extension. You probably don't want to download images you aren't going to use.

The trick is to place the image inside a noscript tag, then progressively enhance that by changing the path as you read the textContent of the tag. In older browsers you will need a simple polyfill to read out the content of noscript tags.

You can view my series on responsive images and webP support here. View an example here based on Ethan Marcotte's classic responsive design.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top