DEV Community

Cover image for 3 easy steps to fix slow image loading
Felix Häberle
Felix Häberle

Posted on

3 easy steps to fix slow image loading

Loading images on the web can be a pain, especially if you are doing a website mainly for mobile devices. Because wireless connection is used in such cases, the transfer speed is often slower compared to a wired connection and therefore the content loads slower.

For text, you might not be able to spot a difference because text gets really fast transported over the web and only weights a few KB's, where images, especially those which have a high resolution, often tend to have a really big file (multiple MB's) size which loads slowly. The easy way would be to exclude the high resolution images, but in most cases, we can't reduce the amount of high-res images so we have to deal with them. Don't worry, I'll show you how to master big images on your website in a minute. ⏱

Tools to the win 🏆

First of all, make sure the images you want to include in your webpage are minimized/compressed. You can accomplish this task with a lot of tools, some of them also guarantee that the overall quality of the image does stay the same. That said, it's good to know how and where the image should be used, because you should optimize it for the use case. For example, a picture which is only displayed as a little icon (possibly 20px/20px) doesn't need to have a resolution of 2000px/2000px because that would be too big. On the other side, a big full-width image shouldn't be that small to keep a nice resolution on the image.

To tackle this task, I can recommend the following sources based on your needs:

🛰 Online image minimization/compression:

📦 Integrate the minimization task into your build/preprocessing (recommended):

Make sure loading images the right way 🔍

Second, a fundamental part of making your loading faster and better is loading the images the right way. Eventually you have heard of lazy loading things, that's when you interrupt the browser to load things immediately and start it over later usually with JavaScript. Lazy loading is used on sites where there are big amounts of images and you can't afford loading all images at once because then your site would take really long to load or eventually would never stop loading (because of you being bored and cancel). To fix this problem, lazy loading only loads images you specified (at first) and loads the other part after an action is happening e.g. the image gets scrolled into the view or some other interaction is happening. 🕹

A few lazyload libraries:

  1. https://github.com/verlok/lazyload (recommended)
  2. https://github.com/tuupola/lazyload
  3. https://github.com/aFarkas/lazysizes

Another solution to load the right image is choosing the right file for the right viewport. There are often images on websites which could be smaller on mobile devices because they scale down on small viewports anyway and could therefore also be smaller in size. To load different images based on the viewport/screen size, you need to monitor the viewport and set in the right image source. 🖼📱

1️⃣ The standard <img> element traditionally only lets you point the browser to a single source file:

<img src="nice-image-900.jpg" alt="This is a very nice image">
Enter fullscreen mode Exit fullscreen mode

2️⃣ For setting up responsive image loading we can use two new attributes — srcset and sizes — to provide several additional source images along with instructions to help the browser pick the right image.

<img srcset="nice-image-340.jpg 340w,
             nice-image-500.jpg 500w,
             nice-image-900.jpg 900w"
     sizes="(max-width: 340px) 300px,
            (max-width: 500px) 450px,
            900px"
     src="nice-image-900.jpg" alt="This is a very nice image">
Enter fullscreen mode Exit fullscreen mode

At first, the srcset and size look complicated, but they aren't that hard to understand. To dive right in, the srcset sets the various images and defines the real widths for them (e.g. 340w -> w not px). To get the real width of the image, you can inspect the image informations on your computer. The sizes attribute describes which image fits best for the current viewport.

At this point, if a supporting browser with a viewport width of 480px loads the page, the (max-width: 480px) media condition will be true, and so the browser chooses the 450px slot. The nice-image-500w.jpg will be loaded, as its inherent width (450w) is the closest to 500w.

Design with image loading in mind 💡

Third, the best solution to prevent slow image loading or loading problems in general is to reduce the overall amount of images which you load initially on your website. The more images you load the slower your site will get and the tips I gave you above are only in the case you can't dispense with it.

Designers tend to do more vector graphics such as SVG these days because SVG files ares basically text and therefore load really quickly. Also, you can modify SVG code to a certain point in your code after loading them which is pretty neat in some cases. Thus, it can be said that SVGs should be used wherever it is possible and images are only used where necessary. Another part of the image loading solution is choosing the right image format in general, a good read about this can be found here.

Thus, it can be said that SVGs should be used wherever it is possible and images are only used where necessary.

Happy coding and improving your images to be lighting fast! 🚀💫

Latest comments (14)

Collapse
 
sushantrahate profile image
Sushant Rahate

For native software also have a look at Caesium Image Compressor. Its awesome and free.

Collapse
 
felixhaeberle profile image
Felix Häberle

Yeah, thanks for sharing that, will definitively try it out!! 🙏

Collapse
 
anwar_nairi profile image
Anwar

Great pieces of advices Felix :) I use them all, verlok/lazyload is astonishing! I also use gulp-reponsive to make variants of my images for each of my supported devices width (smartphone, tablet, desktop, large screen). I recommand it ;)

Collapse
 
felixhaeberle profile image
Felix Häberle

Nice, that makes me happy! Really looking forward to native lazy load 🙏🔥

Collapse
 
pavelloz profile image
Paweł Kowalski
  1. Use small images for small purposes. Meaning: Dont use 1600x1200 1.1MB image when you are using it in a 160x120 img tag.
Collapse
 
felixhaeberle profile image
Felix Häberle

Sure, that's what I wanted to say basically during the whole blog post! Thanks for adding it here! :)

Collapse
 
bassemibrahim profile image
Bassem

I never knew the image tag has those attributes: srcset & sizes. Thanks Felix!

Collapse
 
felixhaeberle profile image
Felix Häberle

No problem, thanks for commenting! 🔥

Collapse
 
nickytonline profile image
Nick Taylor
Collapse
 
felixhaeberle profile image
Felix Häberle

Thanks for pointing this out! That adds huge value in here, I think about update my post based on this information! Thanks! :)

Collapse
 
matthewbdaly profile image
Matthew Daly

I would also add that caching images for as long as possible is prudent, particularly if you're using a CDN. If an image may change in future, you can use various cache-busting techniques to replace the image even if it is cached for a long time.

Collapse
 
catalin560 profile image
catalin560

would you mind explaining a few of those cache-busting techniques?

Collapse
 
matthewbdaly profile image
Matthew Daly

Basically, the idea is that you append a query string to the URL for an asset, usually based on the timestamp when it was last changed. That way, if you replace an image or other asset, the URL used in the application will change, and so you load the new version, no matter how long the old version was cached for.

Many frameworks and CMS's provide this functionality out of the box, such as the version() method in Laravel Mix. If yours doesn't it's not hard to roll your own. Here's a simple example of a Twig filter that does this:

<?php declare(strict_types=1);

namespace App\Views\Filters;

final class Version
{
    public function __invoke(string $path): string
    {
        return DIRECTORY_SEPARATOR . $path . "?v=" . filemtime(PUBLIC_DIR . DIRECTORY_SEPARATOR . $path);
    }
}
Collapse
 
felixhaeberle profile image
Felix Häberle

You're right! That could also be added here, thanks for pointing it out. :)