⚛️ 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
Quick answer: In Next.js, the built-in
next/image component auto-serves WebP to supported browsers — no manual conversion needed. In React with Vite, use the imagetools plugin or Sharp to generate WebP at build time. Use
Convertlo to convert static assets manually.
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
| Feature | Next.js (next/image) | Plain React (CRA / Vite) |
| Auto WebP conversion | ✓ Automatic | ✗ Manual or build tool |
| Responsive srcset | ✓ Automatic | Manual <picture> or plugin |
| Lazy loading | ✓ Default | Add loading="lazy" |
| LCP optimization | priority prop | Manual preload link |
| Blur placeholder | ✓ placeholder="blur" | ✗ Manual CSS |
| Manual pre-conversion needed | No | Yes, 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
Recommended
<picture> element
Manual WebP + JPG fallback. Works everywhere, no build config needed. Best for a small number of images.
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.
What is the next/image priority prop and when should I use it?
The priority prop on next/image disables lazy loading and adds a preload link for the image. Use it on the above-the-fold hero image — the one that is typically the LCP element. Adding priority to your hero image tells Next.js to preload it immediately, improving Largest Contentful Paint (LCP) scores. Do not add priority to images below the fold.