Hero - banner image

Responsive image demo

Call-to-action images

Photo by on Unsplash
Photo by on Unsplash
Photo by on Unsplash
Photo by on Unsplash
Photo by on Unsplash
Photo by on Unsplash

Reading preference



According to the internet, the recommended width is in range of 50-75 characters per line

Code example

When working with images on the web we need to have a couple of things in mind; image codecs (jpg, png, webp, avif), payload size (kb, mb) and resolution. The main focus should be serving appropriately sized images almost regardless of codec, don't use gif or png except for simple graphics.

The main goal:

By serving appropriately sized images we strike the perfect balance of bandwidth payload and image quality. That can be quite tricky because we have to accommodate for:

That can be done by creating multiple versions of the images in different resolutions for each screen size / pixel density and using the srcset attribute in conjunction with the sizes attribute on the <img> element.

srcset defines the set of images we will allow the browser to choose between, and what size each image is. Each set of image information is separated from the previous one by a comma.

sizes defines a set of media conditions (e.g. screen widths) and indicates what image size would be best to choose, when certain media conditions are true

These techniques in combination with the loading="lazy" attribute and we have the perfect recipe for optimized responsive images.

The loading attribute on an <img> element can be used to instruct the browser to defer loading of images that are off-screen until the user scrolls near them.

Now let's dive deeper at our two image implementation above, the hero image and our "Call-to-action" image boxes.

Hero image (banner)

Our banner image spans the whole width of the screen, that means we'll need to accommodate for whole range of screen resolutions, all from mobile phones, laptops to wide monitor displays. Therefor it's best to create images for the lowest resolution to the largest resolution, we will stop at 4k (3840x2560), and with intermediate steps in between.

Example

Here we have a simplified implementation, with some intermediate resolutions removed so it's easier to read.

First we set "a default" image in our src attribute, here we use the 1920x1280 version as it's good balance between high resolution, reasonable payload size and with the "most common" screen resolution. This is good practice in case the browser doesn't support srcset and sizes (all modern browser support attributes, so this should be a problem).

We list our image version in the srcset, the formula being: filename, space, the image's intrinsic width in pixels (denoted with a w not px) and a comma ,.

Last but not least we specify the sizes but in the case of our hero image. For our hero image it always spans the width of the web, so we only have one size to deal with. Therefor we can set 100vw or 100% of the viewport width. By doing so we're telling the browser explicitly how the image will be displayed and the browser can choose the appropriate image size based on that information.

<img src="hero/image-1920x1280.jpg" srcset="hero/image-360x240.jpg 360w,hero/image-960x640.jpg 960w,hero/image-1920x1280.jpg 1920w,hero/image-3840x2560.jpg 3840w" sizes="100vw">

Example with multiple image codecs

In the case of our hero image, and in fact all the images in this demo, we have also created webp and avif versions of our images along with the facto standard jpg format.

We can use the <picture> element and specify each version type with the <source> element and at last using the <img>. Here we can see the <img> does not have srcset nor sizes that's applied to <source>.

Otherwise this setup is really similar to our earlier example, except we specify the image mime type on the <source> element with the type attribute.

<picture>
  <source srcset="hero/image-360x240.avif 360w,hero/image-960x640.avif 960w,hero/image-1920x1280.avif 1920w,hero/image-3840x2560.avif 3840w" type="image/avif" sizes="100vw">
  <source srcset="hero/image-360x240.webp 360w,hero/image-960x640.webp 960w,hero/image-1920x1280.webp 1920w,hero/image-3840x2560.webp 3840w" type="image/webp" sizes="100vw">
  <source srcset="hero/image-360x240.jpg 360w,hero/image-960x640.jpg 960w,hero/image-1920x1280.jpg 1920w,hero/image-3840x2560.jpg 3840w" type="image/jpeg" sizes="100vw">
  <img src="hero/image-1920x1280.jpg" alt="">
</picture>

Why don't we just simplify our setup and use the most efficient codec avif (at the time of writing), with our earlier example?

Not all browser support all codecs, only a few browsers support webp and fewer support avif. By specifying multiple versions the browser can choose what it uses... or based on Google Chrome's behavior it goes in the order from first source to the last, if it's support the first one then it will choose that one.

That means we want to list the most efficient codec first.

Call-to-action images (6 boxes)

For our image boxes the images resize and adopt their layout based on the viewport width. They both shrink and enlargen when the layout switches from 3 boxes to 2, and then to 1 when the viewport shrinks. We deal with this by specifying the sizes and breakpoints with the sizes attribute. See below:

<img src="boxes/image-1-480x320.jpg" srcset="boxes/image-1-320x213.jpg 320w,boxes/image-1-480x320.jpg 480w,boxes/image-1-640x427.jpg 640w,boxes/image-1-960x640.jpg 960w" sizes="(max-width: 680px) 100vw, (max-width: 1024px) 50vw, (max-width: 1300px) 33vw, 420px" alt="Some img">

Let's break these breakpoints/sizes sizes="(max-width: 680px) 100vw, (max-width: 1024px) 50vw, (max-width: 1300px) 33vw, 420px" down:

When determining which size to specify, we don't need to pixel peep there is always some padding and/or margin around the images or their parent elements. We can just take the rough estimate, it's better to be generous rather undershoot it. For example: below 680px viewport width the image is always padded and doesn't tough the edges, but we specify 100vw nonetheless. Because a couple of pixels off won't matter, the browser would still pick the same image.

Final words

Using these browsers natively supported techniques will improve user experience, especially for user with bad/slow internet connection along with lowering bandwidth cost of the host server. Just by serving mobile users, which is quite large amount of all web traffic, the correct resolution, can result in immense bandwidth savings.

This demo uses these techniques to the fullest extent. So please do take a look at this page source, everything is there plain to see.

Sources: