How to properly size images ? /
the right size for the right device

01/09/2024

For most developers it’s easier to scale images in CSS than to create other size versions of the images. So a lot of too big images are loaded on mobile and downscaled in CSS.Use Chrome Developers tools to spot desktop images on mobile

How to fix the big image issue ? Pure HTML approach :

Non optimized :

<img src='https://placeimg.com/800/400/tech' class='img-responsive img-center'>

Optimized :

In this example we provide multiple urls for the same image. The browser will pick a specific url depending on the width of the screen.

<img
  src="https://www.antoinebrossault.com/wp-content/uploads/2024/09/944_w800.png"
  media="(min-width: 320px) 300w, (min-width: 400px) 400w, (min-width: 640px) 600w, (min-width: 1000px) 800w"
  srcset="
  https://www.antoinebrossault.com/wp-content/uploads/2024/09/944_w300.png 300w,
  https://www.antoinebrossault.com/wp-content/uploads/2024/09/944_w400.png 400w,
  https://www.antoinebrossault.com/wp-content/uploads/2024/09/944_w600.png 600w,
  https://www.antoinebrossault.com/wp-content/uploads/2024/09/944_w800.png 800w"
  alt="" class="img-responsive img-center" />

Check this demo on codepen.

An alternative way to do it is to use the picture HTML tag, the srcset attribute allows an <img> element to specify multiple image sources of different resolutions, letting the browser choose the most appropriate one based on the screen size and pixel density. The tag, on the other hand, allows for more complex image switching by combining multipleelements with media queries, enabling different images to be served based on conditions like viewport width or device type.

<img
  src="https://www.antoinebrossault.com/wp-content/uploads/2024/09/944_w800.png"
  media="(min-width: 300px) 300w, (min-width: 400px) 400w, (min-width: 640px) 600w, (min-width: 1000px) 800w"
  srcset="
  https://www.antoinebrossault.com/wp-content/uploads/2024/09/944_w300.png 300w,
  https://www.antoinebrossault.com/wp-content/uploads/2024/09/944_w400.png 400w,
  https://www.antoinebrossault.com/wp-content/uploads/2024/09/944_w600.png 600w,
  https://www.antoinebrossault.com/wp-content/uploads/2024/09/944_w800.png 800w"
  alt="" class="img-responsive img-center" />

If you want to force the browser to display a specific image based on the size, use the <picture> element; otherwise, use the srcset attribute.

Check this demo on codepen.

How to generate different image sizes?

Jimp

You can use Jimp to generate images with node.js:

Jimp is an image processing library for Node.js that allows users to manipulate images, such as resizing, cropping, and applying filters, directly in JavaScript. It supports a wide range of image formats and offers asynchronous methods for handling image processing tasks efficiently.

Here’s a basic usage of Jimp :

const Jimp = require('jimp');
const fs = require('fs');
// our images are in the ./images directory
const directory = "./images";
const imgs = fs.readdirSync(directory);

(async () => {

    for (let img of imgs) {

        const newImg = await Jimp.read(`${directory}/${img}`);

        await newImg.resize(200, 100);

        await newImg.write(`${directory}/${img}.min.jpg`);
    }

})();

Ipx

IPX is an image proxy library for Node.js that allows for dynamic image optimization and transformation, such as resizing, cropping, and format conversion, on the fly. It’s often used in conjunction with frameworks like Nuxt.js to deliver optimized images based on request parameters, improving performance and responsiveness for web applications.

Here’s an example with Express that give you a service to transform images on the fly :

First you need to install the following libraries :

npm install  express ipx listhen 

Create a file called app.js

// app.js 
import { listen } from "listhen";
import express from "express";
import {
  createIPX,
  ipxFSStorage,
  ipxHttpStorage,
  createIPXNodeServer,
} from "ipx";

const ipx = createIPX({
  storage: ipxFSStorage({ dir: "./public" }),
  httpStorage: ipxHttpStorage({ domains: ["origin-playground.antoinebrossault.com"] })
});

const app = express().use("/", createIPXNodeServer(ipx));

listen(app);

Then run node app.js, and you will have your on-the-fly image optimization service ready.

Then, if you run the following HTTP call, the image hosted on origin-playground.antoinebrossault.com will be scaled down to a width of 800px. More option to discover on the project repo

http://localhost:3001/w_800/https://origin-playground.antoinebrossault.com/images/sm_215118145_porsche-944-1982-side-view_4x.png

How to fix the big image issue? Pure CSS approach:

Another technique is to use CSS rules only (background-images & media queries).

Non-optimized:

.my-bg{
    background-image: url(http://lorempicsum.com/futurama/1200/600/3); 
    height: 600px; 
    width: 1200px; 
    max-width: 100%; 
    background-repeat: no-repeat;
    display: block; 
    margin: auto; 
} 

Optimized:

.my-bg{
    background-image: url(http://lorempicsum.com/futurama/1200/600/3); 
    height: 600px; 
    width: 1200px; 
    max-width: 100%; 
    background-repeat: no-repeat;
    display: block; 
    margin: auto; 
} 

/* We add another URL for devices under 768px */
@media only screen and (max-width: 768px){
    .my-bg{
        background-image: url(http://lorempicsum.com/futurama/768/200/3);
    } 
}

Pitfalls

NB: Some phones need bigger images due to the « device pixel ratio ». With srcset the browser will decide which version to display based on the context (e.g., retina display). If you want more control, use the <picture> element.

<img
  src="https://placeimg.com/800/400/tech"
  media="(min-width: 320px) 300w, (min-width: 400px) 400w, (min-width: 640px) 600w, (min-width: 1000px) 800w"
  srcset="
  https://placeimg.com/300/200/tech 300w,
  https://placeimg.com/400/300/tech 400w,
  https://placeimg.com/600/400/tech 600w,
  https://placeimg.com/800/400/tech 800w"
  alt=""
  class="img-responsive img-center"
/>

For example, if we take the code above: on a 400×736 px smartphone with a DPR (device pixel ratio), the image that will be loaded is the 450×400.

DPR Example 1

On the same screen size (400×736) but with a DPR of 2, the image that will be loaded is the 1200×800.

DPR Example 2