Image & Font Optimization
Optimize images with next/image and fonts with next/font
What you'll learn
Use next/image with remote patterns and sizes
Implement next/font with Google Fonts and local fonts
Understand responsive images with srcSet
Apply lazy loading strategies for images
Measure performance benefits of optimized assets
Next/Image
The next/image component provides automatic optimization, lazy loading, and responsive images:
import Image from "next/image"
import heroImage from "@/public/hero.jpg"
export default function Hero() {
return (
<Image
src={heroImage}
alt="Hero banner"
priority // above-the-fold — skip lazy loading
className="rounded-lg"
/>
)
}
Remote Images
For external URLs, configure remote patterns in next.config.ts:
// next.config.ts
import type { NextConfig } from "next"
const nextConfig: NextConfig = {
images: {
remotePatterns: [
{
protocol: "https",
hostname: "images.unsplash.com",
port: "",
pathname: "/**",
},
{
protocol: "https",
hostname: "cdn.example.com",
port: "",
pathname: "/assets/**",
},
],
},
}
export default nextConfig
import Image from "next/image"
export default function RemoteImage() {
return (
<Image
src="https://images.unsplash.com/photo-1517694712202-14dd9538aa97"
alt="Unsplash image"
width={800}
height={600}
sizes="(max-width: 768px) 100vw, 50vw"
className="object-cover"
/>
)
}
Remote Images Need Width/Height
Remote images require explicit width and height or fill prop. Without these, Next.js cannot generate the proper srcSet and responsive dimensions. Use fill with objectFit for container-based sizing.
Before vs After Optimization
Next/Font — Google Fonts
// app/layout.tsx
import { Inter, Roboto_Mono } from "next/font/google"
const inter = Inter({
subsets: ["latin"],
variable: "--font-inter", // use with Tailwind: font-sans
})
const robotoMono = Roboto_Mono({
subsets: ["latin"],
variable: "--font-mono",
})
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html className={`${inter.variable} ${robotoMono.variable}`}>
<body>{children}</body>
</html>
)
}
Local Fonts
import localFont from "next/font/local"
const geistSans = localFont({
src: "./fonts/GeistVF.woff2",
variable: "--font-geist-sans",
display: "swap", // fallback text shows until font loads
})
const geistMono = localFont({
src: [
{ path: "./fonts/GeistMonoVF.woff2", weight: "400" },
{ path: "./fonts/GeistMono-Bold.woff2", weight: "700" },
],
variable: "--font-geist-mono",
})
See It In Action
Build a Gallery with Optimized Images
Code
tsx
1import Image from "next/image"2 3const images = [4{ id: 1, src: "https://images.unsplash.com/photo-1517694712202-14dd9538aa97", alt: "Code" },5{ id: 2, src: "https://images.unsplash.com/photo-1461749280684-dccba630e2f6", alt: "Setup" },6{ id: 3, src: "https://images.unsplash.com/photo-1504639725590-34d0984388bd", alt: "Brain" },7]8 9export default function Gallery() {10return (11 <div className="grid grid-cols-1 md:grid-cols-3 gap-4">12 {images.map((image) => (13 <div key={image.id} className="relative h-64">14 <Image15 src={image.src}16 alt={image.alt}17 fill18 sizes="(max-width: 768px) 100vw, 33vw"19 className="object-cover rounded-lg"20 />21 </div>22 ))}23 </div>24)25}Renders a responsive 3-column grid of remote images using next/image with the fill prop and object-cover for consistent aspect ratio. Uses sizes prop for responsive srcset generation.
Lesson Summary
Key Takeaways
next/image provides automatic WebP/AVIF conversion, lazy loading, and responsive srcSet
Remote images require remotePatterns config and explicit dimensions or fill prop
next/font self-hosts Google Fonts and local fonts — zero external requests, no CLS
CSS variable approach (--font-inter) integrates with Tailwind CSS font families
priority prop above the fold; lazy loading is default for below-the-fold images