Do not use images
This is subjective. Do not use images where it is not necessary.
Always use alternate tags
Alternate tags are meant for search engine bots and screen readers to understand what’s in an image. This might be irrelevant in the future when bots can make sense of an image but until then please use alternate tags on all images without a miss.
<img
src="/path.to/image.img"
alt="A view of the mountains covered with lush green grass"
/>
Always lazy load images
If you have a web page full of images, it is smart to only load the images that the user is viewing instead of all. Lazy loading does exactly that. If an image is in the viewport then it loads it.
It is a little complicated to achieve but it provides a good user experience. Chrome lazy loads images based on a tag. I think all other vendors will follow suit.
<img
src="/path.to/image.img"
alt="A view of the mountains covered with lush green grass"
loading="lazy"
/>
You can use this for your iframe embeds as well.
Optimize images before uploading
Uploading huge images to web pages is one of the most commonly overlooked mistakes I have seen everyone do. This hampers the entire user experience on that web page.
Use an image that is not larger than your viewport. For me, 1000px is more than enough. When you decrease the dimensions of an image, the image file size also decreases.
Webp is one format meant for web images. You can also use SVG images if your images are vectors.
Webp may not work if some devices yet. Use a fallback in such cases
<picture>
<source srcset="img_pink_flowers.webp" type="image/webp" />
<source srcset="img_white_flower.jpg" type="image/jpeg" />
<img src="img_orange_flowers.jpg" alt="Flowers" />
</picture>
These days I prefer using AVIF format for my images. This reduces the file size to under 30KB in most cases.
Do not use AVIF images for OGP tags. Use a JPG or PNG for that. But for all other images, you can use AVIF.
Use object CSS property
Images inside a height and width constrained box don’t look good if you’re not using object proprty.
.image {
width: 560px;
height: 300px;
object-fit: cover;
/* object-fit: contain; */
}
300x300 image without object property
<img height="300" width="300" src="/icon-512x512.png" alt="sample image" />

Using object property
300x300 image with object property
<img
height="300"
width="300"
style="object-fit: contain"
src="/icon-512x512.png"
alt="sample image"
/>

This will make your image look good even if it is shown in different dimensions.
Use multiple images for different screens
Loading a huge image when someone is accessing your web page through their phone doesn’t make sense. This is where source sets come in handy. You can tell the browser to load different images based on the device screen width.
Cache images
Use browser caching so that the browser saves a copy of the images on a page. When the same page is loaded next time it doesn’t have to fetch it from the server.
This can be done on the CDN or in the .htaccess
file. We just tell the browser to save images for a certain length of time. This time can be years as well.
Use height, width, or aspect ratio
When a web page loads, the text and styles comparatively load quicker than images. And once the images load, it will occupy a certain space on the viewport and push everything around it. This is called layout shift. This is a bad UX.
It is recommended to use definite width and height for all the images. But in many cases, we are not sure of the dimensions or we want the image to take the dimensions based on the screen width.
Using aspect ratio can solve the layout shift issue but it is a new property and may not be supported on all browsers.
Use Shimmer Effect before image load
The shimmer effect is a pre-loading animation for images. This also helps mitigate layout shifts.
.shim {
display: block;
height: auto;
width: 100%;
aspect-ratio: 16/9;
object-fit: cover;
object-position: center;
-webkit-animation: shimmer 2s linear infinite;
animation: shimmer 2s linear infinite;
background: linear-gradient(90deg, #eff1f3 4%, #e2e2e2 25%, #eff1f3 36%);
background-size: 1000px 100%;
}
@keyframes shimmer {
0% {
background-position: -1000px 0;
}
100% {
background-position: 1000px 0;
}
}