Long ago the World Wide Web was a hellscape of nothing but text. Then some genius realized you can encode images and have browsers display them and the world was forever changed. But the good also came with some downsizes because images are complicated. Many web developers have stayed up long into the night scratching their heads over how their wonderful creation has gotten so slow only to find out that it was the images.
Today I want to talk about some tips you can use to avoid the most common pitfalls when working with images. We also have a video on this topic, so if you are more of a visual learner feel free to check that out, and without further ado let's get started.
To make our lives easier we are going to start by defining a few terms: Aspect ratio, display size, and Image size.
Aspect ratio is the proportional relationship between an image's width and height. So if the image’s width is 400 pixels and its height is 300 pixels then its aspect ratio is 4:3.
For the other two terms let’s imagine two images of the same aspect ratio 4:3. The first one is a photo you took on your smartphone with the size of 5712 x 4284. However, when you want to display that same image on the site you want it to be 1024 x 768. Image size is the first value i.e. how big the image actually is, while display size is how big your image will be on the page.
Now that we have our definition let’s take a deeper look. The most common aspect ratios are 1:1 which is a square, 4:3 (used in old-school TVs or monitors), and 16:9 (widescreen).
There is no hard rule on which aspect ratios you should use so feel free to use whatever makes your layout look great. The only caveat is that the image aspect ratio should always match the display aspect ratio.
So what happens if the aspect ratios do not match? The browser takes a guess on how you want the image to look and that guess is not always what you had in mind. The end result could be squished, stretched, or cropped depending on several factors, and this makes your site look off.
So what do you do? You edit your photos or change the display aspect ratio. Either works but editing the photos would probably be better in my opinion.
Having said this, I do recognize that there are cases where this might not be possible, like your boss is set on the layout and the image comes from a URL without custom sizes. If you find yourself in one of those cases there are still ways around it. For example, you can use the object-fit
property with either cover or contain and you can even specify where on the image you want to focus. Doing that will make the images look better than letting the browser guess.
The saying goes that a picture is worth a thousand words, and in today’s world with images containing so much data, it has never been more true. Images taken from any modern smartphone these days start from 3MB and can get larger. For example, high-resolution photos from an iPhone Pro Max that can reach 70MB. This doesn’t present a problem when saving to your storage but presents a challenge when displaying those images on the web.
If the display size and image size do not match, one of two things is going to happen. Either the image is going to be expanded or the image is going to be shrunk. Both are done in order to fit the image to the display size and both are bad.
If the image is expanded, it is not going to look great, it will be ballooned out and won’t have great details. If it is shrunk then you’re downloading a larger file than you actually need, and performance will suffer.
To avoid this, make sure the display size and image size match. If you get your images from an API then check if it allows you to specify the size, if you are handling the image locally then it’s worth taking the time to edit them for the web before uploading.
Websites aren’t just displayed on your computer anymore, they can be displayed on your phone, your tablet, a TV, or even a smart teapot.
All those displays have different screen sizes and need different image sizes. So one size no longer fits all. Images displayed on smaller screens will not necessarily need as much details as those displayed on large screens.
This is further complicated because today’s mobile devices come in various pixel densities. Pixel Density when talking displays, is the amount of pixels there are on the screen per inch. For example, high-end phones can have extremely high pixels per inch (PPI) while budget devices have low PPI.
Luckily there is a way to provide different versions of the same image depending on the device. It’s called source-set
. Source Set is an HTML attribute that allows you to specify several sizes for your image and allows you to specify which images are appropriate for which devices.
While at first blush source set looks pretty complicated, it’s pretty straightforward, the srcset
attribute allows you to specify several sources for your image, which display size they should be used for, and even the target PPI. So for example, on low-end mobiles with low density, the browser will only load low-quality images, on desktop it will load the highest quality, and on high-end smartphones, it will load appropriately sized images.
This does have the downside that you will be storing more images on your server, but storage space has been getting cheaper and cheaper so I recommend doing it anyway.
We already talked about display size, but another concern is often overlooked. While browsers don’t force you to specify the display size ahead of time it’s often a great thing to do. If you don’t it can lead to flashes of ugly layout or worse, Cumulative Layout Shift (CLS).
CLS is a very annoying problem on websites and while it has many causes one of them is Images without dimensions. What happens when you don’t specify your display size is that when the image finally loads, the layout will shift to accommodate the image size. But if you specify the display size ahead of time then the browser reserves that space such that when the image loads nothing changes in the layout.
CLS is a huge topic and deserves its own blog post, or a book, but when it comes to images it’s an easy fix, always specify your image’s fixed display size.
Image files contain a lot of data, this is useful when editing or printing. But when they are being displayed on a site, this can be taxing. The last thing you need is for your users to be downloading hundreds of megabytes of images.
The advice here is to use appropriate compression. The caveat is that with compression, the smaller the size, the less detail the images will have. Some people advocate for lossless compression only, but I believe you can lose some detail and it’s not the end of the world.
There are many tools out there that help you do this, such as Tinify but no one size fits all tools exist. You should check out several and find one that works for you.
The good news is that some of these tools can even be integrated into your CMS like Smush on WordPress. But whatever you do, do not use uncompressed image files.
Speaking of…
Please for the love of all that is holy, DO NOT USE BMPs on your site.
Just Don’t!
Images come in many formats, from BMP (short for Bitmap Image file), TIFF (Tagged Image File Format), JPEG (Joint Photographic Experts Group), and PNG (Portable Network Graphic), the list is endless.
Some image formats are not suitable for websites, such as BMPs, TIFFs, and, raw formats like CR2 or NEF from DSLR cameras. This is because BMPs are uncompressed, TIFFs are not supported natively by browsers anymore, and raw formats are both. Mozilla has a nice write-up on image formats you can check out.
You can use the common image formats without issue. i.e. jpegs, pngs, and gifs, but If you are feeling ambitious you can also use the so-called next-gen formats like WebP and AVIF. Another brilliant option is to use vector images like SVG, because they usually have very small file sizes and are highly scalable, so they look good when zoomed in or blown up.
There are no wrong choices… except for BMPs, those are clearly the wrong choice.
Lazy Loading is a technique that defers loading resources until they are needed. For example, if you have images at the bottom of the page and offscreen, loading them at the beginning is pointless. It will block rendering and make the user experience bad.
A better approach is to only load what you need when you need it. So If you have a bunch of images on the page but some of them are not on screen initially, wait to load them. This can be done using the HTML attribute loading
and most frontend frameworks have components that handle it for you.
On a related note, images aren’t the only things you can lazy load, you can lazy load javascript files, CSS, font, etc.
Here is a good write-up on lazy loading. But much like the other tips, use it carefully because if done wrong there might be no performance improvement or in the worst case performance degradation.
The final tip is not performance-based but rather usability-based. In today’s internet landscape, usability is a huge consideration, and search engines like Google take accessibility into account when indexing your site. Try to always have an alt
tag on your images, and make sure your images are not too small or unreadable.
The alt
attribute provides alternative information for an image if a user cannot view it maybe because of a slow connection, an error in the src
attribute, or if the user uses a screen reader.
Also do not overuse or abuse your images, for example by having lots of text in images. Text in images is tricky to index and thus hurts your score.
Having accessible and performant images improves users’ perception of your site and gives you better rankings with search engines.
Images are amazing and elevate websites from little more than wordy books to masterpieces of information presentation. But they have to be handled with care because despite how amazing they are, if done incorrectly they can hurt rather than help your site. That said, making your website images better isn’t that hard and is worth taking the time to do.