Copyright 2017-2018 Jason Ross, All Rights Reserved

Star InactiveStar InactiveStar InactiveStar InactiveStar Inactive
 
HTML5 Logo

In Updating An Old Web Site To HTML5 - Part 1 and Updating An Old Web Site To HTML5 - Part 2 - More Google Analytics "Opportunities" I described the initial updates I made to my site to bring it up to date. There are still plenty of things that Google Analytics and Google Search Console come up with so in this article I'll run through the ones that just won't go away - the image-related ones.

Google Analytics | PageSpeed Insights | Opportunities | Efficiently encode images

This "Opportunity" is displayed for several pages on my site, and in my case is caused by images that were saved with the quality set too high. All of the photos on my site are saved as JPEG images, as you'd expect, but the image quality was generally set to about 90 or 95%. Google feel you can do with lower quality images, and with modern encoding software 80% is perfectly reasonable, and stops Google's complaints.

As I've worked my way through my images, I've been digging out the originals and resizing and re-encoding them to 80% with later versions of Paint.Net and IrfanView. Gradually this message is becoming more rare in my analytics, eventually I hope to get rid of it altogether.

Google Analytics | PageSpeed Insights | Diagnostics | Serve static assets with an efficient cache policy

The assets listed here are mostly JavaScript and other files served by third parties on my site, so despite what Google Analytics says I can't do anything about the caching on those. What I CAN do is set the caching on the images files that show up here from my site. The images don't get changed often, if ever, so setting the duration to around six months should be reasonable and seems to make Google happy.

Google Search Console | Mobile Usability Report

  • Clickable elements too close together
  • Content wider than screen

These errors are left over from Part 1, and are apparently now enough to prevent the pages from being indexed, so it's probably best to fix them.

Let's start with the second error, "Content wider than screen". This was initially a bit of a surprise as everything fits perfectly on my screen. But Google is now crawling my site with its fantastic new "Mobile First" spider, which has a screen width of just over 400 pixels, and that's where things got interesting: a lot of my images are well over 400 pixels across, so obviously this is what causes the problem.

There are a few ways of handling this problem, but the best ones all boil down to one thing - as the size of the browser window changes, you need to display different-sized images.

This was my first venture into "Responsive Design", so I thought I'd start off gently and using HTML5 to display suitably-sized images. I'm only displaying the same image but with different resolutions, so I decided to use the srcset attribute on the <img> tag rather than the <picture> tag.

The first step is to work out what resolutions you want to display. I decided on the following:

  • 150 pixels wide
  • 250 pixels wide
  • 400 pixels wide
  • 600 pixels wide
  • Up to whatever the original picture size was

Now I had to decide the best way to create all of these images. There are a lot on the site, so manually doing this isn't really something I wanted to do. Looking around I had an old version of IrfanView on my system that I hadn't used in ages, so I downloaded the latest version. This has a very handy batch processing feature, where you can specify a directory of images and resize them all, saving them to new files. Setting the names to end with the resolution and running this feature a few times per image directory gives files like:

  • church.jpg
  • church-150.jpg
  • church-250.jpg
  • church-400.jpg
  • church-600.jpg

Now I had to start changing the existing <img> tags from:

<img class="float-right" src="/images/ragged_school_front.jpg"
    title="Chatham Ragged School viewed from the front"
    alt="Chatham Ragged School viewed from the front">

to:

<img class="float-right" src="/images/ragged_school_front.jpg" srcset="/images/ragged_school_front-150.jpg 150w,
             /images/ragged_school_front-250.jpg 250w,
             /images/ragged_school_front-400.jpg 400w,
             /images/ragged_school_front.jpg 600w"
    sizes="(max-width: 1000) 100vw, 80vw"
    title="Chatham Ragged School viewed from the front"
    alt="Chatham Ragged School viewed from the front">

Now seems like a good time to go through what this actually means:

<img class="float-right" src="/images/ragged_school_front.jpg"

First are the class and src attributes, the same as the original tag.

Next the srcset attribute:

srcset="images/ragged_school_front-150.jpg 150w,
        images/ragged_school_front-250.jpg 250w,
        images/ragged_school_front-400.jpg 400w,
        images/ragged_school_front.jpg 600w"

srcset has a couple of possible formats, but this one specifies a list of image files, and their widths in pixels. These are actual pixels in the image, the sort you'll see if you check the image size from your file manager. They're nothing to do with the web page you're displaying them on.

sizes="(max-width: 1000) 100vw, 80vw"

The sizes attribute is a list of media queries that specify the size of the image displayed in viewport width units, depending upon the size of the viewport. The viewport is the width of the browser window in logical pixels rather than absolute pixels. Back in part 1 I mentioned that I set this as a 1:1 ratio with the following item in the <head> section:

<meta name="viewport" content="width=device-width, initial-scale=1">

This simplifies the calculations that I have to do in my design, but if I need to I can change it later.

The media queries in the sizes attribute are the logical equivalent of:

If the viewport is less than or equal to 1000 pixels wide, choose and display an image that takes up around 100% of the viewport. If the viewport is over 1000 pixels wide, display the image at 80% of the viewport width.

title="Chatham Ragged School viewed from the front"
alt="Chatham Ragged School viewed from the front">

The title and alt attributes have their usual meaning: they're the image title shown in tooltips and the alternative text displayed (or read aloud) if images cannot be displayed, respectively.

There are several different ways of using the srcset and sizes attributes with the img element to specify the images to display depending upon the viewport width, but this way does everything I need simply and clearly. It also passes most of the calculation work to the browser, which saves a lot of work on the server side. If you want to change the actual picture or the aspect ratio depending on the viewport width, you should probably look into the picture element instead of the img element.

So far I've done all of these changes manually, partly because so many of the images are different sizes, and partly because my regex skills aren't quite good enough to replace everything automatically. For the moment I'll probably stick with the manual changes, although if I get tired of doing it this way, I might try to come up with some sort of script.

While I was changing the image scaling, I decided I'd take a look at the way the page gets displayed on mobile devices. On large displays, a column is displayed on the right-hand side and contains text and maybe a few advertisements. The page was trying to display in the same way on lower-resolution mobile devices as well, resulting in content that overlapped or ran over the edge of the screen.

Fixing this problem involved some more responsive design, inspired by an article on Medialoot describing how to move sidebars using CSS. I ended up adding a simple media query in the CSS file to set the positioning of the sections of the page depending upon the screen size, something like this:

/*
Mobile and small size screen styles - these should be picked up by default by search engines.
Here we display the article, aside and then footer vertically in that order.
*/

main,
article,
aside,
aside.rightcol,
footer {
    width: 100%;
    float: left;
}

/*
If the viewer is using a screen at least 1000px wide, switch to these styles.
Here we display the article on the left, aside on the right, and footer at the bottom.
*/

@media only screen and (min-width: 1000px) {
    article,
    footer {
        float: left;
        margin: 0 auto;
        text-align: left;
        width: 78%;
    }
    aside,
    aside.rightcol {
        position: absolute;
        float: right;
        top: 15%;
        right: 0;
        width: 20%;
        font-size: 0.7rem;
    }
}

Admittedly my pages' performance has dropped a little, according to Google Analytics, but not so much that you can really tell when you browse the site.

Images That Change When You Hover Over Them

Hover images might not be as trendy as they were, especially as they're not that useful on touch screen devices, but what can I say - when I put them I my site they were cool! Some say they were also a way to get CSS onto my resume, but I couldn't possibly comment on that.

Anyway, if you take a look at my page on St Mary's Island in Chatham, after you've marvelled at the Medway Towns' best known marsh / brickworks / prison / nuclear storage facility / housing estate, you'll see a photo of the construction of two apartment blocks at the bottom. If you hover over that image, you'll see the progress made over a few months as the older photo is instantaneously replaced with the more recent one.

Originally I wondered about using JavaScript to switch a couple of images around, but obviously that wouldn't work if someone viewed the site with JavaScript disabled. Looking around at some ways of doing this with CSS, I found an example using the :hover class - the same class that lets you change link colours when the mouse hovers over them. The images to be displayed need to be the same size, and are joined side by side into one image twice the width of the original. Then the CSS style is used to display one half of the double-width image in an area whose size is specified as the original image size:

<style>
    a.rollover600wide {
        display: block;
        background: url("images/st_marys_island_dockside_from_east_bridge_20080405_20080826.jpg") 0 0 no-repeat;
        width: 600px;
        height: 450px;
        float: left;
    }

    a.rollover600wide:hover {
        background-position: -600px 0;
    }
</style>
<p class="clear-both">
<a class="rollover600wide" href="#">.</a> Walking across the caisson and under the bridge, to the east side of Maritime way, you can look across basin two and see the twin towers being built. This photo was taken at the start of April 2008.

As you can see, the a.rollover600wide class sets the dimensions of the block to 600 pixels wide, and displays the left half of the 1200 pixel wide JPG image as the background. In the paragraph below, there's a link tag with the rollover600wide class, which is then displayed with the image as the background.

When the mouse hovers over, the browser displays the area in the :hover state, which just sets the background position to -600 pixels, which moves the image 600 pixels to the left, displaying the right hand 600 pixels, which contains the other image.

This worked without any problems until Google's crawler checked it and decided that as 600 pixels is wider than the 400+ pixels it was looking for, this page isn't mobile-friendly.

I decided that as there's only one image at the moment that does this, and that I wanted to keep the roll-over effect, mostly out of principle by this stage, I'd use the same technique of media queries and scaled-down images that I use on the rest of the site. I made different-sized copies of the double-width image, and add media queries like these:

In the <head> section:

<style>
    @media screen and (min-width: 170px) {
        a.rolloverImageSwap {
            display: block;
            background: url("images/st_marys_island_dockside_from_east_bridge_20080405_20080826-150.jpg") 0 0 no-repeat;
            width: 150px;
            height: 113px;
            float: left;
        }
        a.rolloverImageSwap:hover {
            background-position: -150px 0;
        }
    }

    @media screen and (min-width: 400px) {
        a.rolloverImageSwap {
            display: block;
            background: url("images/st_marys_island_dockside_from_east_bridge_20080405_20080826-250.jpg") 0 0 no-repeat;
            width: 250px;
            height: 188px;
            float: left;
        }
        a.rolloverImageSwap:hover {
            background-position: -250px 0;
        }
    }

    @media screen and (min-width: 600px) {
        a.rolloverImageSwap {
            display: block;
            background: url("images/st_marys_island_dockside_from_east_bridge_20080405_20080826-450.jpg") 0 0 no-repeat;
            width: 450px;
            height: 338px;
            float: left;
        }
        a.rolloverImageSwap:hover {
            background-position: -450px 0;
        }
    }

    @media screen and (min-width: 800px) {
        a.rolloverImageSwap {
            display: block;
            background: url("images/st_marys_island_dockside_from_east_bridge_20080405_20080826.jpg") 0 0 no-repeat;
            width: 600px;
            height: 450px;
            float: left;
        }
        a.rolloverImageSwap:hover {
            background-position: -600px 0;
        }
    }
</style>

and in the <body> section I kept the:

<a class="rolloverImageSwap" href="#">.</a>

Now the image sizes are displayed using the following logic:

If the viewport is at least 170 pixels wide, display the image specified as 150 pixels wide,

otherwise if the viewport is at least 400 pixels wide, display the image specified as 250 pixels wide,

otherwise if the viewport is at least 600 pixels wide, display the image specified as 450 pixels wide,

otherwise if the viewport is at least 800 pixels wide, display the image specified as 600 pixels wide.

I may need to do a little more work on this for if the display width is less than 170 pixels, but looking through the logs that hasn't happened yet so I'll put that off for the moment. I'll probably see whether instead of displaying a single image at a time, I could just show both images and change the text accordingly.

Now that these changes have been uploaded, Google is complaining less about the images on the site. Most of the remaining warnings are caused by scripts and images on third party sites - things like Google Ads, Google Maps and Amazon Associate ads. Looking over the site, it seems faster and more responsive on both desktop and mobile systems. I'll leave it for the moment, and then take another look at the analytics to see what the next fix should be. This approach of studying the performance of a system, choosing the best part to optimize, optimizing it and then studying the overall performance again is usually the best way to approach any performance problem with any system, not just web sites. If you want to know more about that, take a look at System Performance – Part 1 – Outrun The Bear.