Recently I have developed an application on nextjs 14 and published this app to live server. After that, to improve my page performance i was testing my pages on PageSpeed Insights. And found our one of my section is getting red flag with "Largest Contentful Paint element" on a image. It is top section of my webpage (its a landing page). I have searched and applied lots of solution online, but couldn’t resolve this issue. Here is my full component:
return (
<>
<main className='bg-black text-white'>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
<section className='home-banner-wrapper'>
<div className='basis-[45%] flex flex-col items-start'>
{data?.top_title && (
<h1 className='mb-5 text-[28px] lg:text-[52px] leading-[40px] lg:leading-[66px] font-extrabold'>
{data.top_title}
</h1>
)}
{data?.top_subtitle && (
<p className='mb-[60px] text-xl font-light leading-8 lg:leading-9'>
{data.top_subtitle}
</p>
)}
{data?.cta_link && (
<p className='flex m-0 justify-center items-center'>
<Link
href={data.cta_link}
className='learn-more-btn'
>
Learn More
<Image
src='/images/arrow-circle-right.svg'
width={24}
height={25}
alt="Arrow Icon"
priority={true}
/>
</Link>
</p>
)}
</div>
{data?.banner_image && (
<div className='-mt-[120px] basis-[55%] flex items-stretch'>
<Image
src={data.banner_image}
className='!w-[748px] lg:min-h-[500px]'
width={748}
height={500}
alt="Top Banner"
priority={true}
/>
</div>
)}
</section>
<section className='benefit-list-wrapper'>
{data?.benefit_list
&& data.benefit_list.map((item, index) =>
{
return (
<div key={index} className='flex-1'>
<p className='benefit-list-item'>
{item?.be_icon && (
<Image
className='mb-0.5'
src={item.be_icon}
width={37}
height={38}
alt={""}
/>
)} <span className='pl-1'>{item.be_title}</span>
</p>
</div>
)
})}
</section>
<section className='px-5 2xl:px-0 pt-[88px] mx-auto lg:w-auto'>
{data?.functionality_title && (
<h1 className='text-2xl lg:text-4xl !leading-50 text-center font-semibold'>
{data.functionality_title}
</h1>
)}
{data?.functionality_subtitle && (
<>
<div className='max-w-[290px] bg-secondary h-0.5 mx-auto lg:mt-5'></div>
<p className='text-lg lg:text-[20px] leading-[32px] pt-5 lg:pt-[28px] text-center'>
{data.functionality_subtitle}
</p>
</>
)}
<div className='max-w-[1320px] mx-auto flex flex-col justify-center lg:flex-row lg:justify-between mt-[80px] lg:mt-[50px] lg:pb-[70px]'>
<div className='flex flex-col md:flex-row lg:flex-col md:justify-between gap-y-8 basis-[26%] lg:pt-5 lg:pr-[15px] items-center'>
{data?.functionality_left
&& data.functionality_left.map((item, index) =>
{
return (
<div
className={'flex flex-col items-center min-w-[240px] lg:items-end min-h-[160px]' + (
index == 1 ? " lg:mr-[50px] mt-[7px]" : index == 2 ? " pt-2" : ""
)}
key={index}
>
{item?.icon && (
<Image
src={item.icon}
width={40}
height={60}
alt={item.title || ""}
/>
)}
<h1 className='text-2xl lg:text-[28px] leading-[28px] font-semibold mt-2.5'>{item.title}</h1>
<p className='text-[15px] leading-[28px] font-normal mt-2.5'>{item.subtitle}</p>
</div>
)
})}
</div>
<div className='basis-[48%] flex my-10 lg:my-0 lg:items-center justify-center'>
{data?.image && (
<Image
className='max-w-[unset] lg:-mt-[70px] w-[283px] h-[215px] lg:w-[515px] lg:h-[391px]'
src={data.image}
width={515}
height={390}
alt={data?.functionality_title || ""}
/>
)}
</div>
<div className='md:flex md:flex-row md:justify-between flex flex-col lg:flex-col gap-y-9 basis-[26%] lg:pt-5 lg:pr-[15px]'>
{data?.functionality_right
&& data.functionality_right.map((item, index) =>
{
return (
<div
className={'flex flex-col text-center lg:text-left items-center lg:items-start min-h-[164px]' + (
index == 1 ? " lg:ml-[20px]" : ""
)}
key={index}
>
{item?.icon && (
<Image
src={item.icon}
width={40}
height={60}
alt={item.title || ""}
/>
)}
<h1 className={'text-2xl lg:text-[28px] leading-[28px] font-semibold mt-2.5' + (
index == 2 ? " w-[328px]" : ""
)}>{item.title}</h1>
<p className={'text-[15px] leading-[28px] font-normal mt-2.5' + (
index == 1 ? " w-[311px]" : ""
)}>{item.subtitle}</p>
</div>
)
})}
</div>
</div>
</section>
<section className='px-5 2xl:px-0 pt-[60px] pb-0 lg:pb-[70px] max-w-[1237px] mx-auto'>
{data?.video_title && (
<h1 className='text-2xl font-semibold lg:text-4xl text-center lg:!leading-50'>
{data.video_title}
</h1>
)}
<div className='max-w-[290px] bg-secondary h-0.5 mx-auto mt-5'></div>
{data?.video_subtitle && (
<p className='sm:text-xl text-[16px] pt-[30px] max-w-[903px] mx-auto text-center !leading-1.6'>
{data.video_subtitle}
</p>
)}
{data?.video_subtitle_last && (
<p className='sm:text-xl text-[16px] pt-[30px] max-w-[903px] mx-auto text-center !leading-1.6'>
{data.video_subtitle_last}
</p>
)}
{data?.youtube_video_id && (
<VideoPlayer
divClass="pt-[73px] relative pb-[50%] mt-10 max-w-[1188px] mx-auto"
videoId={data.youtube_video_id}
videoTitle={data?.video_title || ""}
/>
)}
</section>
<section className='px-5 2xl:px-0 pt-[40px] pb-0 lg:pb-[140px]'>
{data?.why_title && (
<h1 className='text-2xl font-semibold lg:text-4xl text-center !leading-50'>
{data.why_title}
</h1>
)}
{data?.why_subtitle && (
<>
<div className='max-w-[280px] bg-secondary h-0.5 mx-auto mt-5'></div>
<p className='text-xl pt-[30px] max-w-[883px] mx-auto text-center text-[16px] leading-8'>
{data.why_subtitle}
</p>
</>
)}
<div className='mt-[50px] grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-y-10 lg:gap-y-[65px] lg:gap-x-[117px] max-w-[1458px] mx-auto'>
{data?.list
&& data.list.map((item, index) =>
{
return (
<div className='text-center basis-1/3 p-5 max-w-[408px] mx-auto' key={index}>
{item?.icon && (
<Image
src={item.icon}
width={60}
height={60}
alt={item.title || ""}
className='mx-auto mb-[14px]'
/>
)}
{item.title && (
<h1 className='text-2xl lg:text-[28px] mb-4 font-semibold'>{item.title}</h1>
)}
{item.subtitle && (
<p className='text-sm lg:text-base font-normal leading-[26px]'>{item.subtitle}</p>
)}
</div>
)
})}
</div>
</section>
<FaqList
faqList={data?.faq_list || []}
id="home-page-faq"
/>
<JoinNow />
</main>
</>
)
And here is the report from pagespeed insights
https://pagespeed.web.dev/analysis/https-nextsono-com/3pv1cjwgw5?form_factor=mobile
Can anyone help me out with this problem? I am getting same problem on other pages as well.
2
Answers
To improve Image output:
Use "Picture" tag
Keep priority="low" & loading="lazy".
If the image is from the first fold then keep its priority="high" & loading="eager".
Must use webp images and if you have SVG then add the package ‘react-svg’ and use it for better output.
Also suggested is using the Next.js dynamic import if not yet used.
Ref: https://nextjs.org/docs/pages/building-your-application/optimizing/lazy-loading#nextdynamic
Ref: how can i fix largest contentful paint issue in next js image
There might be some possible solutions you can try:
The image dimensions you provided are quite large (748×500 pixels), which means the browser needs to download a significant amount of data to render it. You can opt for smaller-resolution images for the mobile device, which might help.
While using
srcset
, downloading and using huge files causes significant performance hits, especially on mobile devices on mobile networks. Just be sure it is not something that’s causing problems here. Also, have a look at this issue which might give you more idea about this.