Speed up image loading time

I’m not sure if this is the right place to post this but I have a ‘gallery’ type page that has to load around 40 images (all 1920 x 1080) and the page is taking ages (around 20 seconds) to load. I came across a couple of site which do what I want but don’t have a huge grasp on JS so am not sure how to do it myself and would be grateful for any help please.

Site one (takes 9 seconds to load) - http://preview.tinyurl.com/y8lzrwjz (these are background images which I don’t want but otherwise is right)
Site two (10 seconds to load) - http://preview.tinyurl.com/yawqvlpu (only has 18 images instead of the 40 odd I want to have).

The code I’ve got for each image is:

<a href="#" class="gallery_link">
        <div class="inner slide">
            <img src="images/12.jpg" />
            <h2 class="header">Title</h2>
            <p class="dateOfExhibit">August 01 2016</p>
        </div>
    </a>

Thanks in advance

Have you tried testing your site in gtmetrix.com ? I tried and gave up it took so long. If you can get it to finish it should give you some ideas as to what needs attention.

Thanks I’ll have a look, I think I know what the issue is though (the images are around1mb each), I’m just not sure how to fix it. I know that if I reduce the image size it’ll speed it up but then they’ll look blurry and the client wants the images to be sharp to show their work clearly.

Do all the images appear full size on the page from the start, or are you displaying thumbnails to expand?

Maybe try AmpProject.org which is very good at loading images. It is essential to ensure the page validates in order to get the full benefit but is well worth the effort because Google caches valid web pages.

Online example page with over a dozen images each about a meg each:

https://www.johns-jokes.com/downloads/sp-h/amp-images-demo/amp-img-001.php

The thumbnail size is dependant on the screen size so on a phone they’ll appear to be much smaller even though the image is the same size

Thanks I’ll have a look at that

If you are only showing thumbnails to begin with, there is no need to be loading the full size images on page load. They can be deferred or loaded on request.

I think I understand what you’re saying, are you saying that I can load small images for different devices? For example if somebody is on a phone then they will probably only need an image to be 475px wide, but on a retina display they will need the full 1920px width.

A common way – especially for large image galleries – would be not to load all images from the start, but only when they actually entered the viewport; this is called “lazy loading”. A basic example might look like this:

<img src="http://lorempixel.com/640/480/city/1" height="400" width="649" alt="City 1">
<img src="" data-lazy-src="http://lorempixel.com/640/480/city/2" height="400" width="649" alt="City 2">
<img src="" data-lazy-src="http://lorempixel.com/640/480/city/3" height="400" width="649" alt="City 3">
<img src="" data-lazy-src="http://lorempixel.com/640/480/city/4" height="400" width="649" alt="City 4">
<img src="" data-lazy-src="http://lorempixel.com/640/480/city/5" height="400" width="649" alt="City 5">
<img src="" data-lazy-src="http://lorempixel.com/640/480/city/6" height="400" width="649" alt="City 6">
<img src="" data-lazy-src="http://lorempixel.com/640/480/city/7" height="400" width="649" alt="City 7">

Note that the images don’t have the src attribute set from the start, but instead stored as a data-lazy-src attribute (can be called anything) which will be applied when they get scrolled into the viewport:

const images = document.querySelectorAll('[data-lazy-src]')
const imgArray = Array.from(images)

const checkImage = (image, index) => {
  // Check if the image entered the vieport
  if (image.getBoundingClientRect().top < window.innerHeight) {
    // Set the actual source of the image
    image.src = image.dataset.lazySrc
    // Remove it from the array to exclude it
    // from future checks
    imgArray.splice(index, 1)
  }
}

const scrollHandler = () => {
  // On each scroll event, iterate over the
  // images and check their position
  imgArray.forEach(checkImage)
  
  if (!imgArray.length) {
    // When there are no images left to lazy-load,
    // listening to the scroll event is no longer
    // required and we can free the resource
    window.removeEventListener('scroll', scrollHandler)
  }
}

// Bind the scroll handler
window.addEventListener('scroll', scrollHandler)
// Also check the images initially
imgArray.forEach(checkImage)

Here’s a pen. You could improve this by loading the images when they come near to the viewport by a certain amount of pixels, and improve performance by debouncing the scroll handler to only check the images when the user finished scrolling.

This is possible too by using a srcset instead of a plain src attribute – here’s a useful article on responsive images:

These two techniques can of course be combined; you’d then just store the srcset as a (say) data-lazy-srcset attribute.

4 Likes

Thank you so much I’ll look at combining those two.

I’ve created a new set of images and tried to load different sizes for different screen sizes but it doesn’t seem to be working. I’ve got the load time down to 10 seconds but I don’t think the lazy loading is working.

This is the site I’m working on but I don’t know why it’s not working.
http://preview.tinyurl.com/yapeg8lh

I’d be really grateful if you could help please

I can’t tell you why lazy loading is not working but I can tell you that if you run your page through gtmetrix as I suggested earlier you will find a number of other matters that need addressing in order to speed up your site.

I have been through that and speeded it up quite a lot over what it was, it’s still really slow. I did try to do the ‘gzip compression’ but when I added the code to the .htaccess file I just got a 500 error so had to undo that

The biggest saving you’re going to get as shown in your gtmetrix report is to optimise your images. You need to do that as well as lazy loading, not instead of.

2 Likes

Yes those images are much too big a filesize and could easily be optimised considerably without a loss of quality to the naked eye.

1 Like

I’ve spoken to the owner of the images and they’re going to optimise them but ideally I’d like to get the lazy loading to work too

The example from @m3g4p0p was for single images not srcsets and will not work unless the code is modified (which is beyond my skills). You missed the data attributes anyway (data-lazy-src).

Unless @m3g4p0p has time to update his example you might try a plugin like this especially for srcset,

2 Likes

Yes, as @PaulOB says you’ll have to set the .srcset properties of the images then, not .src; the line I commented with // Set the actual source of the image thus becomes

image.srcset = image.dataset.lazySrcset

The name of the dataset property does not matter, you might also leave it as is – it just has to match the corresponding data-attribute in the markup. You might check out this article on the MDN for some details on how to access data-attributes with JS. And of course, if you have trouble understanding the above code just let me know and I’ll try to explain. :-)

1 Like

I must be doing something wrong as I’ve changed it to what you said but now none of the images load :frowning: