Optimize Core Web Vitals - FCP and LCP: Images
Pre-study Resources Serve images in next-gen formats Next.js Image Component Documentation Image Optimization Next.js Image Optimization Guide Fix your website's Largest Contentful Paint by optimizing image loading HTMLImageElement Properties Decoding Property FetchPriority Property Loading Property Solution 1: Migrate to Next.js Image Component Conversion Replace elements with the Next.js Image component. To: import Image from 'next/image'; Local Images Local Images Documentation Importing from Public Folder Blog on Next.js Image Usage Image Usage Tips Remote Images Remote Images Documentation Note: Provide either width and height or use fill. Known Width and Height (or Aspect Ratio) Set width and height based on the intrinsic aspect ratio of the image. Unknown Width and Height Extracting Width and Height from Image URL For example, imgUrl: 'http://image-transfer.my.com/myProject/image/upload/ar_1:1,w_700,c_pad,b_auto:predominant/v12345/artist.png'; Helper Function: const parseNum = (value, fallback) => { const num = Number(value); return isNaN(num) ? fallback : num; }; export const getDimensionsFromImgUrl = (imgUrl) => { const defaultSize = 1; const arDelimiter = 'ar_'; const widthDelimiter = 'w_'; const parts = imgUrl.split(','); const arPart = parts.find((part) => part.includes(arDelimiter)); const widthPart = parts.find((part) => part.includes(widthDelimiter)); if (!arPart || !widthPart) return { width: defaultSize, height: defaultSize }; const width = parseNum(widthPart.split(widthDelimiter)[1], defaultSize); const [w, h] = (arPart.split(arDelimiter)[1]?.split(':') || [defaultSize, defaultSize]).map((size) => parseNum(size, defaultSize)); const height = Math.round(width * (h / w)); return { width, height }; }; Usage: const { width, height } = getDimensionsFromImgUrl(imgUrl); When Width and Height Cannot Be Extracted Create a custom image component using the onload event to set dimensions. Note: This may cause layout shift. const DynamicImage = ({ logo, alt, imgUrl }) => { const [dimensions, setDimensions] = useState({ width: 100, height: 100 }); // Fallback values useEffect(() => { const img = new window.Image(); img.src = imgUrl; img.onload = () => { setDimensions({ width: img.width, height: img.height }); }; }, [imgUrl]); return ( ); }; Errors and Solutions Error: 'sharp' is required in standalone mode for image optimization Solution: Sharp Installation Guide Solution 2: Use Next.js Image for Known Dimensions Only HTML Image Element Documentation Since Next.js Image requires width and height (or fill), it is recommended to use it only when dimensions are known. Other Images: Add Attributes to For unknown dimensions, continue using the tag with relevant attributes based on requirements. For example, for LCP (Largest Contentful Paint) images: For non-LCP images:

Pre-study
Resources
Serve images in next-gen formats
Next.js Image Component Documentation
Image Optimization
Next.js Image Optimization Guide
Fix your website's Largest Contentful Paint by optimizing image loading
HTMLImageElement Properties
Decoding Property
FetchPriority Property
Loading Property
Solution 1: Migrate ![]()
to Next.js Image Component
Conversion
Replace
elements with the Next.js Image
component.
<img ... />
To:
import Image from 'next/image';
<Image ... />
Local Images
Importing from Public Folder
Remote Images
Note: Provide either width and height or use fill.
Known Width and Height (or Aspect Ratio)
Set width and height based on the intrinsic aspect ratio of the image.
Unknown Width and Height
Extracting Width and Height from Image URL
For example, imgUrl
:
'http://image-transfer.my.com/myProject/image/upload/ar_1:1,w_700,c_pad,b_auto:predominant/v12345/artist.png';
Helper Function:
const parseNum = (value, fallback) => {
const num = Number(value);
return isNaN(num) ? fallback : num;
};
export const getDimensionsFromImgUrl = (imgUrl) => {
const defaultSize = 1;
const arDelimiter = 'ar_';
const widthDelimiter = 'w_';
const parts = imgUrl.split(',');
const arPart = parts.find((part) => part.includes(arDelimiter));
const widthPart = parts.find((part) => part.includes(widthDelimiter));
if (!arPart || !widthPart)
return { width: defaultSize, height: defaultSize };
const width = parseNum(widthPart.split(widthDelimiter)[1], defaultSize);
const [w, h] = (arPart.split(arDelimiter)[1]?.split(':') || [defaultSize, defaultSize]).map((size) => parseNum(size, defaultSize));
const height = Math.round(width * (h / w));
return { width, height };
};
Usage:
const { width, height } = getDimensionsFromImgUrl(imgUrl);
When Width and Height Cannot Be Extracted
Create a custom image component using the onload
event to set dimensions.
Note: This may cause layout shift.
const DynamicImage = ({ logo, alt, imgUrl }) => {
const [dimensions, setDimensions] = useState({ width: 100, height: 100 }); // Fallback values
useEffect(() => {
const img = new window.Image();
img.src = imgUrl;
img.onload = () => {
setDimensions({ width: img.width, height: img.height });
};
}, [imgUrl]);
return (
<NextImage
className={classNames(
{ 'page-header__img': !logo.isCP },
{ 'page-header-cp__img': logo.isCP },
{ 'page-header__img--sm': logo.sm }
)}
src={imgUrl}
alt={alt}
width={dimensions.width}
height={dimensions.height}
/>
);
};
Errors and Solutions
Error: 'sharp' is required in standalone mode for image optimization
Solution:
Solution 2: Use Next.js Image for Known Dimensions Only
Since Next.js Image requires width and height (or fill), it is recommended to use it only when dimensions are known.
Other Images: Add Attributes to ![]()
For unknown dimensions, continue using the
tag with relevant attributes based on requirements.
For example, for LCP (Largest Contentful Paint) images:
decoding='async'
fetchPriority='high'
loading='eager'
src={resizeImg(imgUrl, 'lg', { ar })}
alt={imgAlt}
/>
For non-LCP images:
decoding='async'
fetchPriority='low'
loading='lazy'
src={resizeImg(imgUrl, 'lg', { ar })}
alt={imgAlt}
/>