EXPEDIA GROUP TECHNOLOGY — SOFTWARE

Images on the Web: Part 1 — Responsive Images

Avoiding the hazards of pixelation, slow loading, and poor cropping

Jorge Barco
Expedia Group Technology

--

Person looking at wall crowded with framed drawings
Photo by Derick McKinney on Unsplash

The term responsive web has been with us since Ethan Marcotte, coined it when he published the article Responsive Web Design [1] in May 2010. Following this idea, website layouts and components should adapt to the size of the viewport where they are displayed.

With responsive images we refer to a similar concept applied to images. We let the browser know what images we have available, how big these images are or even what images we want to use based on the user viewport size.

The browser can then decide what is the best image to use not only based on the screen size and resolution, but also taking into account other aspects such as the available network.

In this blog post, we’ll see the different problems we might face when working with images and how to solve them.

Problem 1: Display resolution

Solution: Resolution switching

What is a Retina display and why we should take it into consideration from the moment we design a component?

Retina®️ displays were first used by Apple®️ when they released the iPhone 4. By doubling the pixel density of the iPhone 3, text looks sharper, and the eye really sees no pixel from a certain distance. That is why they call it retina displays or 2x displays. The device size is the same, but the number of pixels increases 4 times.

As raster images use discrete units (pixels), the more pixels we have, the better the image represents reality as visible below. The downside is that having more pixels means dealing with bigger images and that results in more data consumed, increased rendering times and additional latency.

From left to right: Original shape, shape represented on a 8x8 grid, shape represented on a 16x16 grid.

We need to carefully design our responsive components and take 1x/2x displays into consideration when displaying images. Screens have the same width and height in inches, but since we now have 4 pixels for each regular pixel, we need to quadruple the number of pixels in order to fill the whole screen (we double the pixels on each axis).

In other words, a 320px image might cover the whole screen in a 1x display but only a quarter of the screen on a 2x display.

Image highlighting difference between 200x100 and 400x200 pixels
Scaling 200x100px image in a 400x200px display

When we use small images to cover bigger areas, the rendered image becomes pixelated and the entire user experience might be affected. This happens when we use the same image on both 1x and 2x displays.

The same image presented on two screen types. The left side looks crisp on 1x screen while right side looks pixelated on a 2x screen.
Retina screens will need bigger images for the same space. Otherwise the image looks pixelated.

To avoid this problem, we can inform the browser that we have two image files available:

  • One file for 1x displays (regular)
  • One file for 2x displays (retina) doubling width and height

For example, a 320x320px image rendered on a 1x display will need a complementary 640x640px version for 2x displays.

The term resolution switching relates to declaring several image files for different screen resolutions but using the same size on screen so that the browser can pick up the most suitable one, avoiding blurred/pixelated images. It will consume more bandwidth for 2x displays, but the image will look sharp on the retina screen.

Tip: When showing raster images, we should always let the browser know what image to use for 2x displays. Otherwise, images will be pixelated.

Problem 2: A responsive component uses one image size only

Solution: Set up at least one image per component breakpoint when it makes sense.

Why is this tiny image taking so long to load?

Another image related problem happens when we want to use only one image with a specific size for a responsive component. Imagine you have a component that uses cards to display properties.

The number of cards change based on different breakpoints set up to adapt the component to multiple screen sizes:

Relation of designs for each breakpoint
Mockups with the designs for mobile, tablet and desktop. Mobile has cards with an image as wide as the screen displayed vertically one after the other. Tablets have a two columns design with cards showing an image on the left followed by a title and subtitle on the right. Desktop has a five column design with images as wide as the column followed by title and subtitle below.
Mockup with designs for mobile, tablet and desktop.

As you can see, this component is responsive. It has different layouts and adapts to screen size for a better user experience. We’ll need to implement this component to take into account images of different sizes.

Images for the mockups described before require a 224x224px image for mobile, a 112x58px image for tablet and a 375x180px image for desktop.
Images required for the responsive designs have different sizes and aspect ratios.

Sometimes components are designed for several screen sizes, but the implementation only uses one image size, maybe two based on whether the device is a mobile phone.

If we only provide images based on the device type, we will not give the user a good experience:

  • We might end up downloading huge images to be displayed in small cards, we are forcing the user to wait until the images are fetched.
  • Fetching small images that get rendered pixelated because the browser has to stretch them to cover a bigger area.

Imagine we use the next image to cover the 3 designs described above:

A 290x140px image that has a size of 9.9KB that will be used for all the mockups described above.
This 290x140px image with medium quality has a size of 9.9KB.

Let’s see the impact of using only that image for all mobile, tablet and desktop.

Mobile

Rendering a 375x180px image on a 112x58px rendering area results on a pixelated image as the content has to stretch.
Rendering low resolution images on bigger areas leads to pixelated images.

For mobile sized screens we need to stretch the original image. We are saving some bandwidth, but the cost is that we will display a pixelated image.

Tablet

Rendering a 290x140px image on a 224x224px rendering area results on a pixelated image presenting cropping issues as they have different aspect ratios.
When image to render is smaller than the rendering area and aspect ratio differs, we can have pixelated images combined with cropping issues.

The image will need to stretch or expand depending on how we want the image to fit. In any case, it will look pixelated or blurry.

Desktop

Rendering a 290x140px image on a 112x58px rendering area results in a small image causing a waste of bandwidth.
Rendering high resolution images into smaller areas can be a waste of bandwidth (unless device has a retina display and this is done on purpose).

The image will resize massively in this scenario. The image won’t get pixelated, but instead of this 9.9KB image we could have used another one with the right 112x58px size (about 2.6KB). That is an 84% improvement on the size of the requested image.

You can see the benefit of using the right size when it comes to images, especially when they are used in components like carousels or grids.

The solution is to consider and provide images based on the biggest image needed per breakpoint. That will require some calculations taking margins and paddings into consideration. We’ll review this in a following blog post.

Tip: When working with responsive components, ensure that images have been set up to fit the designed user experience. Otherwise, images will be pixelated or loading times will increase.

Problem 3: The image is cropped and has no meaning for the user

Solution: Design different images based on the component size

This is a very common scenario that happens when we have a responsive component:

  • Using different aspect ratios based on the screen size.
  • Using the same image for all of them.

When an image is cropped, we might lose control of what is rendered and the result might have a negative impact on users:

Set of images highlighting the importance of art direction. The original image shows a person relaxing on a hammock on the beach. Subsequent images display bad cropping experiences, like a squared image with sand, a squared image with the person’s face and a squared image focusing on a pair of feet.
The image on top shows the original image. The three images in the center are examples of how the browser could crop the images in a way we might not intend to. The last image is probably our best option, but we’ll need to make the cropping ourselves and tell the browser to use this version when the screen has a certain size.

Another common mistake it to use a picture with an important and unique focus area that is likely to be cropped out.

Sunset horizon with a person playing with her dog on a beach in the bottom right corner.
If we don’t design the whole experience carefully, we might end up rendering the image with nobody in it, so the image loses the main focus of seeing someone relaxing on the beach with her pet.

This problem can be solved by creating several versions of our artwork, adapting the content to the different aspect ratios used on a responsive component.

Two set of images display how the same image resource can look different if art direction is not set up properly. The images on the left display a beach for mobile, tablet and desktop with no element to focus on. The image on the right shows a different experience as it shows a person playing with her dog on the same beach.
Impact of art direction

Whilst this is a bit tedious and can be managed for components using static images, this solution does not scale very well for images fetched dynamically.

Some CDNs are incorporating features to combine AI to detect objects, people or even faces and auto crop the image centering these elements in the resulting image.

Tip: When working with images presenting different aspect ratios based on breakpoints, ensure that you provide images with the desired elements on the image.

Tip: Explore your CDN features to check if they provide options to detect and focus elements on the cropped image.

Conclusion

In this blogpost we have described how to use resolution switching to display different images for regular and Retina displays.

Moreover, we have covered that fetching the most suitable image for a specific rendering area can improve bandwidth usage, latency and rendering times.

Lastly, we discussed art direction and how providing different versions of an image based on the provided responsive designs can help us to keep focus on what really matters in the image.

References

Graphics in this post were constructed by the author using Adobe Stock images under Enterprise license and Pexels images under Creative Commons Zero license.

--

--