Code Snippets – load SVGs over png + Retina

Todays Code Snippet is a simple bit of javascript to replace images with their SVG or Retina counterparts, whilst keeping the original images size and supporting browsers without SVG support.

 

SVG’s are Scalable Vector Graphics, meaning instead of being pixel-based images, they are a set of mathmatically calculated shapes allowing them to be scaled to any size without losing quality. However, whilst they enjoy a wide support in modern browsers, some legacy software doesn’t support them (Pre IE 11)

First, we need to make sure we have an SVG counterpart of a png image. To do this, we will only replace images that have the data attribute “data-svg” in the image tag. We will also look for “data-vector” attributes in the image tags so we can load in retina images at the normal images size, without slowing down the initial page loading times. I use a PHP function to test whether there is a Retina version of an image and if so put it in the Retina data attribute.

function get_retina($image) {
    $ext = pathinfo($image, PATHINFO_EXTENSION);
    $newimage = str_replace(".".$ext, "@3x.".$ext, $image);
    $file_headers = @get_headers($newimage);
    if(!$file_headers || $file_headers[0] == 'HTTP/1.1 404 Not Found') {
        $newimage = str_replace("@3x", "@2x", $newimage);
        $file_headers = @get_headers($newimage);
        if(!$file_headers || $file_headers[0] == 'HTTP/1.1 404 Not Found') {
            return "false";
        } else {
            return $newimage;
        }
    } else {
        return $newimage;
    }
}

This code requests the image with the @3x and @2x filenames (retina image) and if so returns the new file name. This is used in an image tag like this:

<img src="https://example.com/images/image.jpg" data-retina="https://example.com/images/image.jpg"/>

This function can also be used to check for SVG images pretty easily by changing the function slightly, however, I only use a few SVG in the site this is implemented on, and so I will use the “data-svg” tag manually instead like this:

<img src="https://example.com/images/logo.png" data-svg="http://example.com/images/logo.svg"/>

Now, the fun part. Once the page has loaded, and the images we want to target have their data attributes set, we use javascript and jQuery to find those images, set their height and width to the current size, and replace the images with the selected Retina or SVG images. The reason we set the width and height attributes to what they currently are, is because the Retina images is either 2 or 3 times bigger than the original image, and we want to load it in with the same dimensions as the original. Also, as SVGs are mathematically calculated shapes, they don’t necessarily have their size set, so we need to make sure they also load in at the right size.

To do this, first we use jQuery to select all the images on the page and cycle through each of them. Then, for each images we check whether they have the retina or svg data attributes, we then get the images height and with and it to their corresponding attributes in the img tag. Finally, we replace the src of the img with the new url:

$('img').each(function () {
        var theimage = this;
        var retina = $(theimage).data().retina,
            svg = $(theimage).data().svg;
        if(typeof svg != "undefined" && svg !== "false"){
            if (typeof SVGRect !== "undefined") {
                if (theimage.height !== 0 && theimage.width !== 0) {
                    $(theimage).attr('height', theimage.height);
                    $(theimage).attr('width', theimage.width);
                    if($(theimage).hasClass('cat_image_overlay')){
                        $(theimage).css('height', theimage.height);
					}
                    //console.log(theimage);
                    $(theimage).attr('src', svg);
                }
            } else {
        		if(retina !== "undefined" && retina != false){
                    if(theimage.height !== 0 && theimage.width !== 0){
                        $(theimage).attr('height', theimage.height);
                        $(theimage).attr('width', theimage.width);
                        $(theimage).attr('src', retina);
                    }
                }
            }
        } else {
        	if(retina !== "undefined" && retina != false){
                if(theimage.height !== 0 && theimage.width !== 0){
					$(theimage).attr('height', theimage.height);
                    $(theimage).attr('width', theimage.width);
                    $(theimage).attr('src', retina);
                }
            }
        }
    });
The benefits of this, is that the page first loads with the smaller filesize images, speeding up the load times, and then seamlessly replaces them with their larger files with better quality after the page has loaded. This allows you to keep the speed of your site down, whilst not sacrificing quality.

Check out a working version here!

If you found this useful, or have any questions, leave a comment below and I will try my best to help you out!

Leave a Reply

Your email address will not be published. Required fields are marked *