Optimizing Images and Fonts in Next.js
Images and fonts are the most common causes of slow Largest Contentful Paint (LCP) and layout shift (CLS). Next.js includes components that fix both with very little effort.
next/image
import Image from 'next/image';
import hero from './hero.jpg'; // static import gives width/height automatically
export default function Hero() {
return <Image src={hero} alt="Team working at a whiteboard" priority sizes="100vw" />;
}
- Serves modern formats (WebP/AVIF) at the right size for each device.
- Lazy-loads images below the fold by default.
- Reserves space using width and height, so the layout doesn't jump.
Remote images and sizes
<Image
src={product.imageUrl}
alt={product.name}
width={600}
height={400}
sizes="(max-width: 768px) 100vw, 33vw" // tells the browser which size to download
/>
// next.config.ts - allow images from your CDN
images: { remotePatterns: [new URL('https://cdn.example.com/**')] },
Mark the main above-the-fold image (usually the LCP element) with priority so it isn't lazy-loaded.
next/font
// app/layout.tsx
import { Inter } from 'next/font/google';
const inter = Inter({ subsets: ['latin'], display: 'swap' });
export default function RootLayout({ children }) {
return (
<html lang="en" className={inter.className}>
<body>{children}</body>
</html>
);
}
- Font files are downloaded at build time and served from your domain: no request to Google from the browser.
- Fallback font metrics are adjusted so text doesn't shift when the web font loads.
- Use
next/font/localfor your own font files.
Measure
Check field data in Chrome's CrUX report or Search Console, and lab data in Lighthouse. The useReportWebVitals hook from next/web-vitals sends real-user metrics to your analytics.
Was this article helpful?
Comments
No comments yet. Have a question or a tip? Be the first to share it.