⚛️ React & Next.js Guide

WebP for React & Next.js

Next.js converts images to WebP automatically via next/image. Plain React needs a manual approach — the <picture> element or a build-time tool. Full implementation guide with code examples.

Free WebP converter No upload, no account Batch convert entire /public folder Code examples included

Convert JPG/PNG to WebP for Your Project

For images outside next/image, convert locally — free and instant.

Convert to WebP →

Next.js vs Plain React — Which Approach You Need

FeatureNext.js (next/image)Plain React (CRA / Vite)
Auto WebP conversion✓ Automatic✗ Manual or build tool
Responsive srcset✓ AutomaticManual <picture> or plugin
Lazy loading✓ DefaultAdd loading="lazy"
LCP optimizationpriority propManual preload link
Blur placeholder✓ placeholder="blur"✗ Manual CSS
Manual pre-conversion neededNoYes, for <picture> approach

Next.js — Using next/image (Recommended)

If you're using Next.js, next/image handles WebP conversion, responsive srcset, and lazy loading automatically. You just point it at your original JPG or PNG:

Basic usage
import Image from 'next/image' // Next.js serves WebP to supporting browsers automatically <Image src="/images/hero.jpg" alt="Your hero description" width={1600} height={900} priority {/* ← add this for the LCP/hero image */} />
With responsive fill (covers parent container)
// next.config.js — configure image domains if using remote URLs module.exports = { images: { remotePatterns: [ { protocol: 'https', hostname: 'your-cdn.com' } ], formats: ['image/avif', 'image/webp'], // serve AVIF then WebP } } // In your component <div style={{ position: 'relative', width: '100%', height: '400px' }}> <Image src="/images/hero.jpg" alt="Hero image" fill style={{ objectFit: 'cover' }} priority /> </div>
When next/image doesn't apply: CSS background images, Open Graph images (og:image), images served from the /public folder via direct URL, and images in email templates. For these, convert to WebP manually using Convertlo.

Plain React — Three Approaches

Build tool
vite-imagetools (Vite)

Auto-convert at build time via import query. Best for Vite projects with many images.

Build tool
imagemin-webp-webpack

Webpack / CRA plugin. Generates .webp files alongside originals at build time.

Approach 1 — <picture> element (manual WebP + fallback)
{/* First: convert hero.jpg → hero.webp using Convertlo */} {/* Then use both in your component */} function HeroImage() { return ( <picture> <source srcSet="/images/hero.webp" type="image/webp" /> <img src="/images/hero.jpg" alt="Hero description" width={1600} height={900} fetchPriority="high" {/* for LCP element */} style={{ width: '100%', height: 'auto' }} /> </picture> ) }
Approach 2 — vite-imagetools (Vite projects)
# Install npm install vite-imagetools --save-dev # vite.config.ts import { imagetools } from 'vite-imagetools' export default { plugins: [imagetools()] } # In your component — auto-converts at build time import heroWebp from './hero.jpg?format=webp' import heroJpg from './hero.jpg' <picture> <source srcSet={heroWebp} type="image/webp" /> <img src={heroJpg} alt="Hero" width={1600} height={900} /> </picture>
Approach 3 — Reusable WebP component
// components/WebPImage.tsx interface Props { src: string // path without extension, e.g. "/images/hero" alt: string width: number height: number priority?: boolean className?: string } export function WebPImage({ src, alt, width, height, priority, className }: Props) { return ( <picture> <source srcSet={`${src}.webp`} type="image/webp" /> <img src={`${src}.jpg`} alt={alt} width={width} height={height} loading={priority ? 'eager' : 'lazy'} fetchPriority={priority ? 'high' : 'auto'} className={className} /> </picture> ) } // Usage — assumes both hero.webp and hero.jpg exist in /public/images <WebPImage src="/images/hero" alt="Hero" width={1600} height={900} priority />

WebP for CSS Background Images in React

CSS background-image doesn't use the <picture> element. Serve WebP directly and let the browser handle it — WebP is supported by 97%+ of browsers:

/* CSS — use WebP directly for background images */ .hero { background-image: url('/images/hero.webp'); background-size: cover; } /* If you need a JPG fallback for older browsers */ .hero { background-image: url('/images/hero.jpg'); /* fallback first */ } @supports (background-image: url('x.webp')) { .hero { background-image: url('/images/hero.webp'); } }

For CSS background images in React/Next.js components, just convert to WebP using Convertlo and reference the .webp file directly. The @supports fallback is optional — fewer than 3% of users lack WebP support.

React & Next.js Image Performance Tips

Next.js priority
Add priority to your hero Image

The priority prop on next/image adds a preload link and disables lazy loading. Add it to the first above-the-fold image — the one that is the LCP element. Missing this is the most common Next.js LCP mistake.

Dimensions
Always specify width and height

Both next/image and plain <img> need explicit width and height to prevent CLS (Cumulative Layout Shift). Without them, the browser can't reserve space — content jumps as images load.

og:image
Keep og:image as JPG even in Next.js

Your og:image meta tag URL should point to a JPG. Social media crawlers (LinkedIn, Slack, Twitter) sometimes mishandle WebP og:image. Keep the og:image as JPG; use WebP for page content images.

Formats config
Enable AVIF in next.config for cutting-edge compression

Add formats: ['image/avif', 'image/webp'] in next.config images settings. Next.js will serve AVIF (even smaller than WebP) to Chrome 85+, WebP to other supporting browsers, and JPG as fallback.

Sizes prop
Use the sizes prop for responsive images

sizes="(max-width: 768px) 100vw, 50vw" tells Next.js how large the image appears at each breakpoint — so it generates the right srcset entries. Without it, Next.js generates all sizes unnecessarily.

public/ folder
Images in /public bypass next/image optimization

Files in the /public folder served at their direct URL (e.g. /logo.png) are NOT converted by next/image. Pre-convert these to WebP manually using Convertlo.

Frequently Asked Questions

Does Next.js automatically convert images to WebP?
Yes, via the next/image component. It converts JPG and PNG to WebP for supporting browsers, generates responsive srcsets, and lazy loads by default. You provide the original image — Next.js handles WebP delivery via /_next/image. Images in /public served directly as static files bypass this optimization.
How do I use WebP in a React app without Next.js?
Manual approach: Convert your JPG/PNG to WebP using Convertlo. Use the <picture> element with a WebP source and JPG fallback. Build tool approach: Use vite-imagetools (Vite) or imagemin-webp-webpack-plugin (Webpack/CRA) for automatic build-time conversion. The <picture> approach is simplest for a few images; build tools scale better for large projects.
Should I use next/image or a regular img tag?
Always next/image for content images — it provides automatic WebP, lazy loading, blur placeholder, and the priority prop for LCP optimization. Use a regular img (or <picture>) for images in CSS backgrounds, email templates, og:image references, or images served directly from /public as static assets.
Do I need to pre-convert images to WebP in a Next.js project?
For images used via next/image — no. Next.js converts at request time and caches the result. But you should pre-convert images that are: (1) in /public served directly by URL, (2) used as CSS background-image, (3) referenced in og:image meta tags (though keep og:image as JPG for crawler compatibility), (4) used in non-Next.js parts of your stack.
How do I use WebP for CSS background images in React?
Convert your image to WebP using Convertlo, then reference it directly in CSS: background-image: url('/hero.webp'). WebP is supported by 97%+ of browsers — a JPG fallback via @supports is optional. For critical above-the-fold background images, add a preload link: <link rel="preload" as="image" href="/hero.webp"> to avoid render-blocking.

Related Tools