Optimize images and media elements for a faster website
Of all the parts of a website that have an effect on its overall weight, images, and multimedia elements usually have the greatest impact. In fact, the HTTP Archive Page Weight report shows that in the majority of cases graphical elements and images account for approx. two-thirds of the total page size.
For this reason, if you want your site running as fast and smoothly as possible you'll certainly need to examine the images or other multimedia elements on your website since it is here that you'll most likely find the largest opportunity for optimization. Though this can be a long-winded task, the speed benefits that it provides can be much more noticeable than other, simpler optimizations, so it's absolutely worth investing the time.
Image Dimensions
One of the most common mistakes people make when building their site (that is also one of the most impactful in terms of site weight and load speed) is using images sizes that are inappropriate for our needs. Website owners will often download photos in high resolutions and then upload them directly to their site without taking any other steps.
This is a big problem, as it almost always leads to a significant increase in the size of the files a user's browser must download when visiting the site. Remember that photos that you download or even those you take with your own camera/phone will include additional elements (such as EXIF data) that provide metadata for the photo, but don't directly affect the quality. Photos taken with your own camera will also often be RAW; that is, a pure image file that is usually not compressed in any way. This is great when editing photos, but not so much when uploading those photos to a website where the size of the file may be a concern.
Therefore, it's a good idea to audit the images on your site and verifying whether there's any opportunity for reducing the file sizes while still maintaining the site's aesthetic appeal; this may be through compression or resolution reduction, removal of metadata, etc...
A certain exception here would be images that are intended to be displayed on high-resolution screens - in this situation the images should be 2-3 times larger than the area in which they are displayed to ensure maximal quality. And if we really care about the quality of our photos and how they appear on these types of screens, then we are doomed to a heavier website (though it will certainly look great!). In this case, it's worth looking into whether the use of vector graphics would be a better option that provides some speed benefits, though this isn't always possible.
Choosing the appropriate image format
The format that you choose for the photos on your site plays a very important role is achieving the perfect quality to size ratio that works best for your site's needs. The most common image formats are JPG and PNG. JPG format allows us to control the quality of the photo (at the expense of size) and it's great in many conditions, particularly when the photo content is not uniform in terms of color and gradient (which is generally the case with most photos).
On the other hand, PNG format is a lossless format that supports transparency, making it better suited when we want to make some parts of an image transparent to blend it with our other page content. However, the resulting files in this format are often much larger than JPG files; even more so when using typical images than have irregular patterning and colors. PNG format works best with regular patterns and coloring; in this situation, you may find that PNG images are actually smaller in size than JPG images.
Speaking from personal experience, PNG images can often be replaced with SVG images instead. This is especially true when working with illustrations that utilize transparencies, rather than standard image. The one great advantage SVG format has over both PNG and JPG is its theoretically infinite resolution; SVG images use a vector format (i.e. its elements are laid out using mathematical formulas) and not raster (i.e. the image is stored as a series of lines of pixels), which means that the image can be scaled while retaining its quality; something that isn't as simple with other formats.
In practice, however, you also have to be careful here - when using a very small but detailed image in SVG format, it may look worse than the same image in regular PNG or JPG format.
Though it's now rather archaic, we can't talk about image file types without mentioning the GIF format. Though this format has many limitations such as 1-channel transparency and a maximum of 256 colors, it is still relatively popular since it is possible to animate (if you've seen a short repeated video clip on social media, for example, then it was probably in GIF format). But if you want the benefits of the GIF format but with improved quality and transparency, then it's worth checking out the APNG format. It boasts quite impressive support across modern browsers: https://caniuse.com/?search=apng, and lets you add animated images to your site at a far higher quality than GIF.
It may seem that we've covered a lot in this section, but in reality, we're only just scratching the service of the challenges of choosing a format and configuration for photos on your site. A good introduction to this subject is provided in this article: https://kornel.ski/en/faircomparison
WebP format
In the previous section I intentionally omitted one format, because I believe it deserves to be highlighted separately since it may be a great option as adoption rates of modern browsers increases - WebP. This format offers a much more effective level of compression than JPG or PNG, but includes the advantages of transparency that PNG provides.
However, it's not necessarily the answer you're looking for, especially if your website's audience isn't up-to-date with their browser. Previously, its main drawback was that it lacked support, especially on macOS and iOS. Fortunately, for some time (more precisely from iOS 14 and macOS 11 Big Sur) this format has enjoyed native support across the most popular browsers, which has significantly expanded the range of its applications.
Before using it, however, it is imperative that you ensure that your userbase will be able to see images displayed in this format: https://caniuse.com/?search=webp
If your userbase is split across multiple browsers and multiple versions, but you still want to get the benefits of the WebP format, then it's a good idea to use the tag to generate images in two formats, WebP and PNG/JPG, so that users on older browser version are still able to view the images on your site, though with the added weight cost that comes with the older formats.
Responsive images
As support of the sizes
and srcset
attributes became the norm, it became possible to deliver different sizes of images to a user's browser depending on the screen size and resolution of the device. While in the case of smaller images this is not a big problem, as the differences between the display area and the size of the image are usually not so large, special attention should be paid to more prominent elements such as page headers where there are usually large image and the benefits of loading smaller images for smaller screens will be at their highest.
The <picture> tag
The <picture>
tag currently has very good support across browsers (https://caniuse.com/?search=picture), but due to its rather complicated structure, I have the impression that it is still not used very widely despite its versatility.
With the <picture>
tag, we can handle:
- Support for various formats
- Support for responsive images
- Support for browsers that do not support the
<picture>
tag (fallback image)
If, for example, we want people using browsers that lack support for the WebP format to see our site's images in PNG format instead, we can use the following tag:
<picture>
<source src="image.webp" type="image/webp">
<source src="image.jpg" type="image/jpeg">
<img src="image.jpg">
</picture>
The <picture>
tag works by looking for the first tag that contains the images that meet the specified criteria (in the above case, we're using the supported image type as the filter which decides which image to load). Additionally, if we want to be absolutely safe it's worth adding a standard <img>
tag at the end for browsers that don't support the <picture>
tag to use.
In turn, to implement responsive images using the <picture>
tag, we can use:
<picture>
<source src="image-small.jpg" media="(max-width: 640px)">
<source src="image-medium.jpg" media="(max-width: 1024px)">
<img src="image-large.jpg">
</picture>
Note that there is no third tag for the largest image - instead, the fallback image <img>
tag is used both when no criteria are met from the source tags (i.e. for screens that are larger than the defined max-width in the source tags), or the browser doesn't support the <picture>
tag.
Lazy-loading images
The loading attribute is a relatively new solution that can have a huge impact on the speed of image rendering, although its support is not quite perfect yet: https://caniuse.com/?search=loading
When using the loading attribute, you should remember two things :
- Always specify the dimensions of the images through the width and height attributes to avoid the content being shifted around the page when loading images.
- For images that you want users to be able to see as quickly as possible, you should use eager loading to ensure they are loaded first, without waiting for the user to scroll the viewport.
If we want to offer broader support for lazy-loading our images, we should look to older, yet still effective solutions based on the use of data-src attributes, which are changed into the src attribute when scrolling, which causes the image to be loaded only when needed. For best results, we should combine this solution with the use of the Intersection Observer (which has much better support than the loading attribute itself: https://caniuse.com/?search=intersection%20observer) to minimize the impact of scripts on page performance.
What else can be done to optimize the amount of data and images?
Sometimes, to optimize the resources used on the website, you need to be quite inventive. Fortunately, web technologies offer us a constantly growing catalog of tricks and techniques that can help us in this task.
Image maps (also SVG)
I expect that any old-timers who were creating pages back when gradients or rounded corners were not supported by browsers remember using the technique of limiting the number of graphics on the page through so-called sprites. It is a technique that consists in creating one collective image that contains many illustrations, which are then displayed by specifically-selecting the background-position value.
Currently, a similar technique is used for SVG graphics - SVG sprites are very convenient to use and at the same time allow you to drastically reduce the number of images loaded, especially since the SVG format is often used for icons that are characterized by the fact that they are small but numerous files, which can slow down page loading quite severely.
You can learn more about SVG Sprites here: https://w3bits.com/svg-sprites/
Inline embedded images
An alternative to optimizing the loading of very small images is embedding them in the CSS / website code via the so-called URI date. With this, instead of providing a link to the image, we provide the code that represents the content of the image - most often in base64 format. The disadvantage of this solution is that images saved in base64 format are heavier than the original image, so it only makes sense for small images to avoid increasing the size of our CSS code too much.
Preload images with media queries
When you want to load a given image as quickly as possible (to improve the First Contentful Paint metric; that is, to reduce the time between the page starting to load, and the user actually seeing something on the screen), you should consider using the link tag with the rel = "preload" attribute. This allows us to tell the browser that you want to load and display image data as soon as possible:
<link rel="preload" as="image" href="/path/to/image.png" />
You should also be aware that, with this tag, we can also handle the sizes and srcset attributes in the form of imagesrcset and imagesizes:
<link rel="preload" as="image" href="/path/to/imgage-small.jpg" imagesrcset="/path/to/image-small.jpg 640w, /path/to/image-medium.jpg 1024w, /path/to/image-large.jpg 1280w" imagesizes="50vw" />
This will allow the device screen size to be taken into account when preloading such graphics. Unfortunately, the attributes needed to add responsiveness to preloaded images does not yet have browser support across the board, so it's not a universal solution that we can rely on: https://caniuse.com/?search=imagesrcset
SVG and transparent JPG graphics
With some creative use of SVG masks combined with the advantages of the JPG format, we can achieve transparency as in the PNG format while keeping the file size closer to a JPG file. So, if a transparent WebP file does not meet our expectations in terms of size, we can check whether applying a transparency mask to an image in JPG format will bring better results.
You can learn more about this technique here: https://css-tricks.com/transparent-jpg-svg/
Multiple backgrounds as an optimization method
If you're running into issues with optimizing your images, you should consider breaking the images into smaller components where possible. This solution can be especially useful when we have a small and repeating pattern in the background of the page, on which an additional effect, e.g. a gradient, is applied. If we extract a repeating pattern into a small image, duplicate it, and then apply a gradient to it (whether by using CSS gradients or PNG / WebP graphics), it's very likely that as a result, we will get much better quality and a much smaller resulting image size:
#section- with-pattern {
background-image: url (pattern.png), url (gradient-effect.png);
background-position: center center, right top;
background-repeat: repeat, no-repeat;
background-sizes: 10px 10px, 50% 100%;
}
Instead of icons, use special characters from fonts or emojis.
If we need simple and small decorative elements, special characters or emoji may be more than enough for our needs, rather than loading additional images.
However, we should remember that the main disadvantage of emoji is that they are displayed differently depending on the operating system; this isn't such a good solution when we want to ensure a consistent site experience across different devices.
Fun fact: some special symbols are automatically converted to emoji, which may not always be desired, e.g. when using arrows. Fortunately, you can get around this by using special characters that affect the selection of the emoji variant: https://mts.io/2015/04/21/unicode-symbol-render-text-emoji/
A very helpful website to keep to hand when adding special text characters rather than images to your site is copypastecharacter.com; on this site you can explore the full range of special characters and instantly grab their HTML codes to easily add them to your content.
Summary
When optimizing images on a website, the format and size of the images play a key role, and should be your first port of call in the optimization process. Then, by using techniques such as lazy-loading and other optimizations that are aimed at minimizing the number of requests that are sent to the server, we can further improve the page load time. In special cases where a large number of images are used, we should look to alternative methods for displaying heavier images, though when doing so we must also be aware of the limitations and level of browser support that each format or solution has in order to find the perfect balance between supporting our users and providing them a fast a seamless site experience.