To automatically load the image that fits the current screen size, you need to set the srcSet and sizes attributes.
srcSet and sizes are attributes of the img tag that display the appropriate image based on the size.
One of the key factors in determining web page performance is images. They significantly impact FCP (First Contentful Paint) and LCP (Largest Contentful Paint), which influence user experience and bounce rates. So, how can we optimize images?
Image optimization methods can be broadly divided into two categories.
1️⃣ Image Optimization Techniques
Lazy Loading
Preloading
Progressive Loading
2️⃣ Reducing the Size of Loaded Images
This article focuses on the second method—reducing the actual size of images.
Using smaller images speeds up loading times and improves performance. However, one question might come to mind:
"Won’t reducing image size lower its quality?"
That’s true, but consider this analogy:
Imagine Hyunbin orders 10 servings of beef at a restaurant but only eats 2 servings, leaving the other 8 untouched. Ordering 10 servings was a waste of money. When we dine out, we don’t order excessive amounts just because we can—we order based on what we can actually eat.
The same principle applies to images. If a large image is downloaded but isn’t fully displayed on the screen, unnecessary data is loaded, increasing page load time. That’s why we should resize images to the optimal size that fits the current screen.
There are two ways to properly reduce image size:
1️⃣ Responsive Image Loading
Use attributes to serve images based on screen size.
Load smaller images on mobile and larger images on desktops.
2️⃣ Using the Right File Format
Use WebP instead of JPEG to reduce file size while maintaining quality.
If transparency is needed, convert PNG to WebP.
Finally, responsive image loading + modern formats are the key.
This approach leads to faster loading speeds, a better user experience, and lower bounce rates.
To set the optimal image size, you need to consider the target service and predefined breakpoints (responsive thresholds). Each service has different breakpoints, which determine the necessary image sizes.
For example, in a React project with breakpoints at 480px, 800px, and 1400px, you would need three different image sizes. Serving the appropriate image for each screen size is the most optimized approach.
Before optimization, the results of loading a generalized image across different viewports are as follows:
Each viewport requires a different image size, but all of them download the same image, resulting in poor LCP (Largest Contentful Paint) performance.
(There is an automated way to do this. You don't need to follow the manual steps. 😀)
Using tools that help resize images to the desired size is very convenient.
Link: https://www.responsivebreakpoints/
After optimizing the images, you can save them in the project's public/images and public/resized folders.
<img
srcSet="
/image/image-test_small.webp 480w,
/image/image-test_medium.webp 800w,
/image/image-test_large.webp 1400w"
sizes="
(max-width: 480px) 100vw,
(max-width: 800px) 100vw,
70vw"
src="/images/image-test-1.jpg"
alt="image test 1"
/>
To sum up, WebP is the most efficient in terms of file size and functionality, so it should be prioritized. However, since there might be browsers that don’t support WebP, JPG and PNG can be used as backups depending on the use case.
Now, let's use a tool to convert the file extensions.
Link: https://bigconvert.11zon.com/ko/jpg-to-webp/
Simply by changing the file extension, you can see that the image size has been reduced by about 30%.
Finally, after implementing all images responsively, you can check the Network tab and measure the performance to see a significant difference. Different images are loaded for each viewport, and an improvement of over 63% in LCP was observed.
Understanding how to create responsive images, convert file extensions, and optimize the images for loading based on breakpoints and services is important. However, when creating a webpage, a large number of images are used. Manually using tools to create multiple versions of each image and converting file extensions can become a cumbersome and repetitive task. As a developer, performing repetitive tasks over and over is not efficient. Fortunately, there is a way to automate this process.
Depending on the bundler, library, or framework you're using, there is a solution available. For example, in Npm + Vite, there is a library called Sharp. This library automatically regenerates images in the desired size and version, and it also converts the extensions to your preferred format. Here's how to use it:
1. Download Library
npm i sharp
2. Create the script
import sharp from "sharp";
import fs from "fs";
import path from "path";
// Folder containing the original images
const inputDir = "./public/images/";
// Folder to save the converted images
const outputDir = "./public/generated/";
// List of image sizes to generate
const sizes = [480, 800, 1400];
// Create the output folder if it doesn't exist
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
// Get all image files in the folder
fs.readdir(inputDir, (err, files) => {
if (err) {
console.error(`Directory read error: ${err.message}`);
return;
}
// Execute conversion for all images
files.forEach((file) => {
const inputPath = path.join(inputDir, file);
const ext = path.extname(file).toLowerCase();
// Convert only supported extensions (jpg, png, jpeg)
if ([".jpg", ".jpeg", ".png"].includes(ext)) {
const baseName = path.basename(file, ext);
sizes.forEach((size) => {
const outputPath = path.join(outputDir, `${baseName}-${size}.webp`);
sharp(inputPath)
.resize(size) // Resize the image
.webp({ quality: 80 }) // Convert to WebP format
.toFile(outputPath)
.then(() => console.log(`${outputPath} conversion complete!`))
.catch((err) => console.error(`Conversion error: ${err.message}`));
});
}
});
});
3. Apply the Script
//in pakage.json
"scripts": {
"gi": "node scripts/generate-images.js",
"dev": "vite",
"build": "tsc -b && vite build"
},
5. Use Script
npm run gi
6. Result
Using this method, you can generate responsive images and change the file extensions for all images within your project. By following the steps mentioned earlier, you can optimize the images, which will significantly improve the performance of your project. This automated process ensures that the images are properly resized, converted to more efficient formats like WebP, and optimized for faster loading times.
By reducing image sizes and using appropriate formats for different screen sizes, you can enhance FCP (First Contentful Paint) and LCP (Largest Contentful Paint), improving overall user experience and reducing bounce rates.