Introduction
Before we start let’s setup NextJs, To set up the Next js project we can follow this setup nextjs project blog that covers all about the next js project setup.
NextJs introduced the Image component in the framework, providing a performant way to deliver images on the web.
Images are a crucial part of modern web application development, impacting both the developer and user experiences.
Traditionally, web designers used the HTML <img> tag to add images to web pages, but this approach can become untidy for large amounts of images.
The Image component features built-in automatic image optimization, which helps to improve the performance of your application.
By leveraging the Image component, you can optimize and develop performant applications, improving the developer and user experiences.
In this section, we’ll learn how to use the Image component to optimize and develop performant applications.
We’ll explore the benefits of using the Image component, including improved performance, better SEO ranking, and better developer experience.
We’ll also discuss how to use the Image component with NextJS, including how to import and use the component in your applications.
Things we can cover in this blog:
- Optimization
- Responsiveness by defining custom ‘srcSet’
- The NextJS Image Component
- Different properties in NextJs image component
- Other next/image props
- Configuration Options
NextJs image optimization
Before using the Image component, it’s important to optimize your images for performance.
If you have a large amount of dynamic images, consider using a CDN like Amazon Cloud front, google cdn or cloudinary to host your images.
Before serving your images to end-users, consider choosing the appropriate image format, optimizing the size, compressing the quality using appropriate dimensions, using image compression tools.
Here are some points you should consider before serving images to End-users:
Choose the right and optimized format in NextJs
- The three most popular image formats on the web are JPEG, PNG, Avif & WebP.
- WebP and Avif is highly recommended due to it’s many advantages and performance benefits.
- WebP is a modern image format that provides superior lossy and lossless image compression for web images without compromising quality. on the other hand, Avif Provides better compression and faster loading times compared to WebP after first load.
- Using a tool like WebP-Converter/Avif converter can help you convert your images to WebP or Avif format, which is supported by most modern browsers.
Get Image size according to device needs in NextJs Image component
- Serving the right images for the right device sizes is crucial for optimizing image performance on the web.
- Serving a huge 1080 x 800 image for users with 100 x 100 device sizes can lead to unnecessary bandwidth usage, slowing down page loads and affecting performance metrics.
- The Responsive Breakpoints Generator tool by various CDN providers is a good tool for generating multiple image file sizes for different screen sizes.
- By generating multiple image file sizes, you can serve the right image for the right device size, reducing the amount of unnecessary bandwidth usage and improving performance.
- The Responsive Breakpoints Generator tool also provides options for serving images in different formats, including WebP and AVIF, which can further improve performance.
For optimization follow these things
- A good rule of thumb for image optimization is to keep your images below 1 Mb.
- Large file sizes should be reduced to a reasonable threshold without sacrificing image quality.
- Using a tool like Compressor.io can help you compress your images without losing too much quality.
- ImageOptim is a free tool that can compress your images in bulk and optimize their size for web use.
- By compressing your images, you can improve the performance of your website and reduce the load time of your images.
Image component
- The NextJs Image component is a built-in solution for optimizing images in NextJs applications.
- It provides a simple and intuitive API for optimizing images, including support for lazy loading, responsive images, and image optimization.
- The NextJs Image component supports a variety of image formats, including JPEG, PNG, WebP, and AVIF.
- It also supports automatic optimization of images, including resizing, compressing, and converting images to WebP format.
- The NextJs Image component also provides support for lazy loading, which can help improve the performance of your application by only loading images when they are needed.
Further, You can use this like this:
First of all import it as
import Image from "next/image"; //After importing you can use this component as: <Image priority alt="alt-field" src="image-url" width={700} height={575} objectFit="fill" style={{ width: "100%", height: "auto", maxHeight: "100%" }} />
Properties/Attributes of NextJs image tag
Here, some properties/attributes provided by Next.Js to make a better user experience using next image tag:
Some necessary or required props by NextJs image component:
Src
- A path string. This can be either an absolute external URL, or an internal path depending on the need.
- When using an external URL, you must add it to remotePatterns in
next.config.js
.
Width and height
The width
and height property represents the rendered width in pixels, and it will affects on the rendered size of the image or quality of the visible image.
Required, you can ignore this if you are using fill prop.
Alt attribute
- Image alt tags provide alternative text for images, which can improve accessibility for users who are visually impaired or using assistive technologies.
- Image alt tags should be descriptive and provide enough information for users to understand the content of the image.
- Image alt tags should be unique for each image and not contain any personal information or sensitive information.
- It is also the fallback text if images have been disabled or an error occurs while loading the image.
Some option props supported by NextJs image component:
Priority
- The
priority
property can be used to prioritize images for lazy loading, which can improve the performance of your application by loading images on priority basis. - Setting
priority
totrue
will cause the image to be considered high priority and pre-load its default value is false. - Lazy loading is automatically disabled for images using priority.
- You should use the
priority
property on any image detected as the Largest Contentful Paint (LCP) element. - It may be appropriate to have multiple priority images, as different images may be the LCP element for different viewport sizes.
- The
priority
property should only be used when the image is visible above the fold.
Sizes
- The image’s size at different breakpoints and the performance of the downloaded image are provided by the sizes property.
- We can use it to serve various images based on different devices with varying screen sizes, pixel densities, resolutions, orientations, aspect ratios, file formats, and compression levels. The browser utilizes the value of sizes to decide which image size to download from next/image’s automatically generated srcset.
- When the browser chooses, it does not yet know the size of the image on the page, so it selects an image that is the same size or larger than the viewport.
- The sizes property allows you to tell the browser that the image will actually be smaller than full screen. If no sizes value is present, a small srcset is generated, suitable for a fixed-size image.
- If sizes is defined, a large srcset is generated, suitable for a responsive image. If the sizes property includes sizes such as 50vw, which represent a percentage of the viewport width, then the srcset is trimmed to not include any values which are too small to ever be necessary.
- If no
sizes
value is present, a smallsrcset
is generated, suitable for a fixed-size image (1x/2x/etc) suitable for a responsive image.
<Image fill src="image-url" sizes="(max-width: 768px) 100vw, (max-width:1200px) 50vw, 33vw" />
Quality
The quality of the optimized image, an integer between 1
and 100
, where 100
is the best quality and therefore largest file size. Defaults to 75
. Maximum quality mean large size image.
<Image fill src="image-url" sizes="(max-width: 768px) 100vw, (max-width:1200px) 50vw, 33vw" quality={75} />
fill
The fill
property is a boolean that causes the image to fill the parent element, which is useful when the width and height are unknown.
The parent element must assign position: “relative”, position: “fixed”, or position: “absolute” style.
By default, the system will automatically assign the position: “absolute” style to the img element. If there are no styles applied to the image, it will stretch to fit the container.
You might prefer to set the image with object-fit: “contain” to make it letter-boxed, fit the container, and preserve aspect ratio.
Alternatively, you can make the image fill the entire container and cause it to be cropped to preserve aspect ratio with object-fit: “cover”.
To make this look correct, you should assign the overflow: “hidden” style to the parent element.
loader
The loader
property is a custom function used to resolve image URLs.
In addition, it is a function returning a URL string for the image, given the src
, width
, and quality
parameters.
The loader
function can be used to modify the URL of the image, add query parameters, or use a different URL altogether.
The loaderFile
configuration in next.config.js
can be used to configure every instance of next/image
in your application, without passing a prop.
//Example: const imageLoader = ({ src, width, quality }) => { return `https://example.com/${src}?w=${width}&q=${quality || 75}` } export default function Page() { return ( <Image loader={imageLoader} src="me.png" alt="Picture of the author" width={500} height={500} /> ) } // and if you are defining through next-config // next.config.js module.exports = { images: { loader: (src, { width, quality }) => { return `https://example.com/${src}?w=${width}&q=${quality || 75}` }, }, }
placeholder
The placeholder
property is a placeholder to use while the image is loading. It can have three possible values: blur
, empty
, or data:image/...
. The default value is empty
.
When blur
, the blurDataURL
property will be used as the placeholder.
If the src
is an object from a static import and the imported image is .jpg
, .png
, .webp
, or .avif
, then blurDataURL
will be automatically populated, except when the image is detected to be animated.
For dynamic images, you must provide the blurDataURL
property. Solutions such as Placeholder can help with base64 generation.
When data:image/...
, the Data URL will be used as the placeholder while the image is loading.
When empty
, there will be no placeholder while the image is loading, only empty space.
style/className
The style
property is used to apply inline styles to an element. It takes an object with CSS property-value pairs as its value.
The className
property is used to apply CSS classes to an element. It takes a string with the name of the CSS class as its value.
NextJs some advance props of next/image components are:
onLoad
The onLoad
property is a callback function that is invoked once the image is completely loaded and the placeholder has been removed.
Furthermore, It is a function that takes in one argument, the Event
which has a target
that references the underlying <Image
> element.
Besides, the onLoad
function can be used to perform actions on the loaded image, such as resizing or cropping it.
//example const [isImage, setImage] = useState(false); const onLoadCallBack = (e)=>{ setImage(true) typeof onLoad === "function" && onLoad(e) } return( <div> {!isImage && 'loading image...'} <Image onLoad={onLoadCallBack} src={'/'+image} alt={title} width={260} height={160} /> </div> )
onError
A callback function that is invoked if the image fails to load.
//example export const Thumbnail = () => { const [src, setSrc] = useState<any>(placeholder_image); /** * Settings SRC after receiving it from the server */ useEffect(() => { if (thumbnail) { setSrc(thumbnail); } }, [thumbnail]); const onError = () => { setSrc(PLACEHOLDER_IMG); }; return ( <Image onClick={onClick} src={src} fill={fill} loading={loading} width={width} height={height} priority={priority} placeholder={placeholder} blurDataURL={PLACEHOLDER_IMG} alt={alt} onError={onError} /> ); }; export default Thumbnail;
loading
The loading behavior of the image. Defaults to lazy
.
When lazy
, defer loading the image until it reaches a calculated distance from the viewport.
When eager
, load the image immediately.
Note: Remember that if you are loading images on priority always than set loading to eager always else, it will hurt the performance alot.
blurDataURL
The blurDataURL
property is a Data URL to be used as a placeholder image before the src
image successfully loads.
It only takes effect when combined with placeholder="blur"
.The blurDataURL
must be a base64-encoded image.
It will be enlarged and blurred, so a very small image (10px or less) is recommended. Including larger images as placeholders may harm your application performance.
NextJs unoptimized
“unoptimized” is a prop that can be passed to the “Image” component in NextJs to serve the source image as-is instead of changing its quality, size, or format. The default value is “false”.
To use this prop, you can create a custom component called “UnoptimizedImage” that wraps the “Image” component and passes the “unoptimized” prop to it. Here’s an example:
Image from 'next/image' const UnoptimizedImage = (props) => { return <Image {...props} unoptimized /> }
Since NextJs 12.3.0, you can also assign this prop to all images by updating the “next.config.js” file with the following configuration:
module.exports = { images: { unoptimized: true, }, }
This will ensure that all images are served as-is by default, without any quality, size, or format changes.
deviceSizes
deviceSizes is a property that allows you to specify a list of device width breakpoints for the next/image component.
These breakpoints are used to ensure that the correct image is served for the user’s device. If no configuration is provided, the default values are used.
In the next.config.js file, you can specify the device sizes like this:
module.exports = { images: { deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840], }, }
imageSizes is a property that allows you to specify a list of image sizes for the next/image component.
These sizes are combined with the list of device sizes to create the complete list of sizes used for generating image srcsets.
The reason there are two separate lists is that imageSizes
is used only for images that provide a sizes
prop.
Which indicates that the image is less than the full width of the screen.
Therefore, the sizes in imageSizes should all be smaller than the smallest size in deviceSizes. If no configuration is provided, the default values are used.
In the next.config.js file, you can specify the image sizes like this:
module.exports = { images: { imageSizes: [16, 32, 48, 64, 96, 128, 256, 384], }, }
Formats supported by NextJs
This is a property that allows you to specify the image formats that are supported by the Image Optimization API. The default value is “image/webp”.
If the Accept header matches more than one of the configured formats, the first match in the array is used. Therefore, the order of the formats in the array matters.
If there is no match or the source image is animated, the Image Optimization API falls back to the original image’s format.
If you don’t provide any configuration, the system will use the default value.
In the “next.config.js” file, you can specify the image formats like this:
module.exports = { images: { formats: ['image/webp'], },
You can also enable AVIF support by adding “image/avif” to the list of formats.
AVIF generally takes 20% longer to encode compared to WebP, but it compresses 20% smaller.
This means that the first time you request an image, it will typically be slower, but subsequent cached requests will be faster.
If you self-host with a proxy/CDN in front of NextJs, you must configure the proxy to forward the Accept header.
In the next.config.js file, you can enable AVIF support like this:
module.exports = { images: { formats: ['image/avif', 'image/webp'], }, }
Note: if you self-host with a proxy/CDN in front of NextJs, you must configure the proxy to forward the Accept header.
This is because the Image Optimization API relies on the Accept header to determine which image format to serve to the user’s browser.
Creating responsive images in NextJs
By using picture and source tag by defining different image according to different viewport :
We use the “sizes” prop to specify the image sizes for different screen widths.
For styling, we used the “style” prop to set the object-fit property to “cover” and the width and height to 100%.
Here, We used the “maxHeight” property to limit the height of the image to 100% of the container.
To provide different image according to device we used the “source” elements to provide different image sources for different screen sizes.
For example, we will use the first “source” element if the screen width is less than or equal to 500px, which will provide a smaller image.
We will use the second “source” element if the screen width is between 501px and 1000px, and this will provide a medium-sized image.
<div style={{ width: "100%", height: "80vh", position: "relative", }} > <picture> <source media="(max-width: 500px)" srcSet="https://images.unsplash.com/photo-1682685797332-e678a04f8a64?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" /> <source media="(max-width: 1000px)" srcSet="https://images.unsplash.com/photo-1682685797332-e678a04f8a64?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" /> <Image layout="responsive" alt="Mountains" src="https://images.unsplash.com/photo-1682685797332-e678a04f8a64?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" width={700} height={475} sizes="(max-width: 400px) 100vw,(max-width: 768px) 75vw, (max-width: 1200px) 60vw,(max-width: 1500px) 50vw,(max-width: 2100px) 30vw, 33vw" style={{ objectFit: "cover", width: "100%", height: "auto", maxHeight: "100%" }} /> </picture> </div>
Overall, this code demonstrates how to use the “next/image” component to optimize images for different screen sizes and formats, making it a great choice for building responsive websites.
For Single Image:
Finally, If you want to make single image responsive for all view-ports you can use sizes attribute provided by NextJs default:
<Image src={me} alt="Picture of the author" // sizes="(max-width: 400px) 100vw,(max-width: 768px) 75vw, (max-width: 1200px) 60vw,(max-width: 1500px) 50vw,(max-width: 2100px) 30vw, 33vw" sizes="100vw" style={{ width: '100%', height: 'auto', }} /> ) }
Here, NextJs automatically generates custom srcsets according defined sizes.
But for extreme cases and for extra large screens source method is preferable.
Conclusion
Here, we have covered automatic lazy-loading, pre-loading of critical images, automatic sizing across devices, and automatic support for modern image formats.
Lastly, by using this powerful component, you can create visually appealing and responsive websites that load quickly and provide a seamless user experience.
In addition, With its numerous customization options and features, you can optimize your images for different screen sizes and resolutions.
And, it ensures that your application is fast and optimized for performance.
This article has helped you start building amazing developer and user experiences by leveraging the power of next/image.
With its easy-to-use API and comprehensive documentation, furthermore, you can quickly and easily optimize your images and improve the performance of your NextJs application.
Start your Headless Development with Webkul.
Happy Coding !!
Be the first to comment.