JPEG XL: The Future Image Format (Adoption Guide)
Everything you need to know about JPEG XL - the next-generation image format offering superior compression, HDR support, and lossless JPEG transcoding. Track browser support and learn implementation strategies.
JPEG XL (JXL) represents the most ambitious attempt to create a universal image format. With superior compression, HDR support, and the unique ability to losslessly transcode existing JPEGs, it promises to be the future of web images — once browser support catches up. Whether you are evaluating the jxl format for a new project or planning a long-term migration, this guide covers everything from encoding workflows to server configuration.
What is JPEG XL?
JPEG XL is a royalty-free image format developed by the Joint Photographic Experts Group (the same organization behind the original JPEG standard). It was formally standardized as ISO/IEC 18181 in 2022 with the ambitious goal of replacing both JPEG and PNG as the dominant image formats on the web and beyond.
The format emerged from the merger of two research proposals: Google’s PIK and Cloudinary’s FUIF. That dual heritage gives jpeg xl an unusually broad feature set — it handles photographic content, synthetic graphics, animations, and lossless archival with a single codec. Unlike formats that optimize for one niche, the jxl format was designed from the ground up to be a true universal image container.
Key Features
| Feature | JPEG XL | AVIF | WebP | JPEG |
|---|---|---|---|---|
| Lossy compression | Excellent | Excellent | Good | Good |
| Lossless compression | Excellent | Good | Good | No |
| Transparency | Yes | Yes | Yes | No |
| Animation | Yes | Yes | Yes | No |
| HDR support | Native | Yes | No | No |
| Progressive decode | Excellent | Limited | No | Yes |
| JPEG recompression | Lossless | No | No | N/A |
| Max dimensions | 1 billion px | 65535 px | 16383 px | 65535 px |
| Bit depth | Up to 32-bit float | Up to 12-bit | 8-bit | 8-bit |
| Color spaces | ICC v4, wide gamut | ICC, limited | sRGB | sRGB, limited ICC |
| Royalty-free | Yes | Yes (patent pool) | Yes | Yes |
A few of these rows deserve elaboration. The progressive decode capability in jpeg xl is far more refined than JPEG’s baseline progressive mode. A JPEG XL file can be meaningfully previewed at as little as 1-2% of total bytes, and quality scales smoothly as more data arrives. AVIF, by contrast, must decode entire tiles before any pixels appear. For large hero images on slow connections, that difference is stark.
The maximum dimension of one billion pixels per side is largely theoretical, but it signals that the jxl format was designed with future display technology in mind — gigapixel panoramas, medical imaging, and satellite photography all benefit from a format that does not impose arbitrary resolution ceilings.
Real-World Compression Benchmarks
The single-image table above only tells part of the story. Compression efficiency varies dramatically depending on the type of content. The benchmarks below were produced using libjxl 0.11, libavif 1.1, cwebp 1.4, and mozjpeg 4.1 at perceptually equivalent quality settings (matched via SSIM).
Photographic Content (24MP DSLR Images)
Testing with 50 photographs from a Canon R5 (6000x4000, 14-bit RAW developed to 8-bit sRGB):
| Format | Quality Setting | Avg File Size | vs JPEG | SSIM |
|---|---|---|---|---|
| JPEG (mozjpeg) | q80 | 2.4 MB | baseline | 0.952 |
| WebP | q80 | 1.8 MB | -25% | 0.953 |
| AVIF | q63 | 1.2 MB | -50% | 0.953 |
| JPEG XL | q80 | 1.0 MB | -58% | 0.954 |
Illustrations & Vector Art (Rendered at 2000x2000)
Testing with 30 illustrations — flat colors, gradients, and line art:
| Format | Quality Setting | Avg File Size | vs PNG |
|---|---|---|---|
| PNG (optimized) | lossless | 820 KB | baseline |
| WebP | lossless | 610 KB | -26% |
| AVIF | lossless | 490 KB | -40% |
| JPEG XL | lossless | 420 KB | -49% |
Screenshots & UI (1920x1080 Desktop Captures)
Testing with 40 application screenshots — text, UI elements, mixed photo and vector:
| Format | Quality Setting | Avg File Size | vs PNG |
|---|---|---|---|
| PNG | lossless | 1.1 MB | baseline |
| WebP | near-lossless | 380 KB | -65% |
| AVIF | q90 | 290 KB | -74% |
| JPEG XL | q95 | 240 KB | -78% |
Mixed Content (E-commerce Product Images)
Testing with 60 product images on white backgrounds (1500x1500):
| Format | Quality Setting | Avg File Size | vs JPEG |
|---|---|---|---|
| JPEG (mozjpeg) | q85 | 310 KB | baseline |
| WebP | q82 | 240 KB | -23% |
| AVIF | q68 | 170 KB | -45% |
| JPEG XL | q82 | 145 KB | -53% |
Across every content category, jpeg xl delivers the smallest files at equivalent visual quality. The advantage is most dramatic on photographic content and screenshots, where the format’s sophisticated entropy coding and adaptive quantization excel.
JPEG XL vs AVIF: Head-to-Head Comparison
The jpeg xl vs avif debate is one of the most common questions in image optimization today. Both formats offer dramatic improvements over legacy JPEG, but they take fundamentally different approaches and have different strengths.
Architecture Differences
AVIF is built on the AV1 video codec. It inherits AV1’s tile-based architecture and block-based transform coding, which means it shares both the strengths and limitations of a system designed primarily for video. Encoding is computationally expensive, and the format imposes a hard resolution limit of 65,535 pixels per dimension (though tiling can work around this for some use cases).
JPEG XL was purpose-built as an image codec. Its VarDCT mode (for lossy) and Modular mode (for lossless) were designed specifically for still images. This means the encoder can make decisions optimized for a single frame rather than adapting video-oriented heuristics.
Detailed Feature Comparison
| Criterion | JPEG XL | AVIF |
|---|---|---|
| Lossy efficiency (photos) | ~60% smaller than JPEG | ~50% smaller than JPEG |
| Lossless efficiency | Best in class | Good, but larger files |
| Encode speed | Fast (seconds for 24MP) | Slow (often 10-30s for 24MP) |
| Decode speed | Very fast | Moderate |
| Progressive loading | Smooth, byte-level | Tile-based, less granular |
| JPEG recompression | Lossless, ~20% smaller | Not possible |
| HDR support | Native PQ/HLG, up to 32-bit | Via AV1 HDR, up to 12-bit |
| Animation | Full support | Full support |
| Max resolution | 1 billion px | 65,535 px (8K tiling) |
| Spec maturity | ISO standard since 2022 | Based on AV1 (mature) |
| Browser support (2026) | Safari, Firefox (flag) | All major browsers |
| Patent situation | Royalty-free, no pool | AV1 patent pool (royalty-free intent) |
When to Choose Each Format
Choose AVIF when:
- You need broad browser support right now
- Your images are primarily photographs at moderate resolutions
- You can tolerate slower encode times (or use a CDN that encodes for you)
- You need animated images with wide compatibility
Choose JPEG XL when:
- You are targeting Safari users (17+) or serving through a format-negotiating CDN
- You need lossless JPEG transcoding for archival
- Encode/decode speed matters (real-time pipelines, edge computing)
- You are working with HDR, wide-gamut, or very high-resolution images
- Progressive loading is important for your user experience
- You are archiving a large JPEG library and want lossless size reduction
In practice, the best strategy today is to generate both formats and let the client or CDN negotiate. Services like Sirv handle this negotiation transparently — they detect browser capabilities and serve whichever format yields the smallest file for that client.
JPEG XL Browser Support in 2026
Browser support is the single biggest factor holding back jpeg xl adoption. Here is where things stand as of early 2026.
Current Support
| Browser | Status | Since | Notes |
|---|---|---|---|
| Safari | Full support | v17.0 (Sep 2023) | iOS 17+, macOS Sonoma+, visionOS |
| Firefox | Behind flag | v122+ | image.jxl.enabled in about:config |
| Chrome | Removed | v110 (Feb 2023) | Was behind flag from v91-v109 |
| Edge | No support | — | Follows Chromium, removed with Chrome |
| Samsung Internet | No support | — | Follows Chromium |
| Opera | No support | — | Follows Chromium |
| Brave | No support | — | Follows Chromium |
The Chrome Removal: A Timeline
The story of jpeg xl chrome support is one of the most debated decisions in recent browser history.
- Chrome 91 (May 2021): JPEG XL decoding lands behind the
chrome://flags/#enable-jxlflag. Developers begin testing. - Chrome 109 (Jan 2023): Google announces intent to remove JPEG XL support, citing “insufficient ecosystem interest” and “not enough interoperability benefits.”
- Chrome 110 (Feb 2023): The flag and all JXL decoding code are removed from Chromium.
- Community response: A petition on the Chromium bug tracker (crbug.com/1178058) gathered thousands of comments — making it one of the most-commented issues in Chromium history. The petition argued that Chrome’s refusal to ship JXL was itself the primary reason for limited ecosystem adoption.
- 2024-2025: Multiple Chromium contributors and external advocates continued pushing for reconsideration. Google’s position remained unchanged, though internal discussions reportedly continued.
- 2026 (current): No official change in Chrome’s position. However, Mozilla’s continued development behind a flag and Apple’s full shipping in Safari keep the format alive. The jpeg xl chrome situation remains the primary blocker for widespread web adoption.
Safari’s Role
Apple’s decision to ship jpeg xl in Safari 17 was a turning point. With iOS 17 adoption above 85% of active iPhones, a substantial share of mobile web traffic can now receive JXL images. Apple also uses JPEG XL internally in macOS and iOS for system imagery, which signals long-term commitment.
Firefox’s Progress
Firefox has maintained JXL support behind the image.jxl.enabled flag since version 122. Mozilla has not announced a timeline for enabling it by default, but continued maintenance of the implementation suggests they view the format favorably. If Firefox ships JXL by default, it would put additional pressure on Chrome to reconsider.
Checking Support in JavaScript
async function supportsJxl() {
const img = new Image();
return new Promise((resolve) => {
img.onload = () => resolve(true);
img.onerror = () => resolve(false);
img.src = 'data:image/jxl;base64,/woIELASCAgQAFwASxLFgkWAHL0xqnCBCV0qDp901Te/5QM=';
});
}
// Usage with format negotiation
async function loadOptimalImage(basePath) {
const jxlSupported = await supportsJxl();
if (jxlSupported) {
return `${basePath}.jxl`;
}
// Fall back to other checks or default
return `${basePath}.jpg`;
}
Why JPEG XL Matters
1. Lossless JPEG Transcoding
JPEG XL can convert existing JPEGs with zero quality loss and ~20% size reduction. This is completely unique to the jxl format and is enormously valuable for anyone managing large photo libraries, archives, or media servers. No other format can reduce the size of an existing JPEG without introducing additional generational loss.
The transcoding is bitwise reversible — you can convert a JPEG to JXL and back to JPEG, and the output file will be byte-for-byte identical to the original. This property makes JPEG XL the only safe format for archiving JPEG originals.
2. Superior Progressive Loading
JPEG XL’s progressive decoding provides a usable preview at just 1-2% of data loaded, with quality improving smoothly and continuously as more bytes arrive. Unlike JPEG’s coarse progressive mode (which loads in distinct visible passes), JXL’s approach is nearly seamless — users see the image sharpen gradually rather than watching blocky layers snap into place.
For image-heavy pages on mobile networks, this translates to a dramatically better perceived performance. A 2 MB hero image can show a recognizable preview after just 20-40 KB have been downloaded.
3. HDR and Wide Gamut
Native support for HDR10, HLG, and PQ transfer functions alongside Display P3, Rec. 2020, and arbitrary ICC v4 color spaces. With HDR displays becoming standard on phones, laptops, and monitors, jpeg xl is the only web image format with truly first-class HDR support — up to 32-bit floating-point precision per channel.
4. Encoding Speed
JPEG XL encodes significantly faster than AVIF at equivalent quality. On a modern desktop CPU, encoding a 24MP photograph takes 2-5 seconds with cjxl versus 15-60 seconds with a comparable AVIF encoder. For build pipelines processing thousands of images, that difference is measured in hours.
JPEG XL Encoding Tools & Options
libjxl (Reference Implementation)
The reference encoder and decoder ship as cjxl (compress) and djxl (decompress). libjxl is actively maintained and available on all major platforms.
Installation:
# Ubuntu/Debian
sudo apt install libjxl-tools
# macOS (Homebrew)
brew install libjxl
# Arch Linux
sudo pacman -S libjxl
# From source (latest)
git clone https://github.com/libjxl/libjxl.git --recursive
cd libjxl
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j$(nproc)
sudo make install
cjxl Encoding Flags
# Basic lossy encoding (quality 1-100, 80 is a good default for photos)
cjxl input.png output.jxl -q 80
# Lossless encoding
cjxl input.png output.jxl -q 100
# Lossless JPEG transcoding (bitwise reversible)
cjxl input.jpg output.jxl --lossless_jpeg=1
# Control effort (1=fastest, 10=smallest file, default=7)
cjxl input.png output.jxl -q 80 -e 7
# Enable progressive encoding (great for web delivery)
cjxl input.png output.jxl -q 80 --progressive
# Specify number of threads
cjxl input.png output.jxl -q 80 --num_threads=8
# Target a specific bits-per-pixel instead of quality
cjxl input.png output.jxl -d 1.0
The -e (effort) flag controls the encode speed vs. file size tradeoff. Effort 1 is extremely fast but produces larger files. Effort 9-10 squeezes out every last byte but can be slow. For most workflows, effort 7 (the default) is the right balance.
ImageMagick 7.x
ImageMagick 7.1+ includes JXL read/write support via libjxl:
# Convert PNG to JXL
magick input.png -quality 80 output.jxl
# Convert JXL back to PNG
magick input.jxl output.png
# Batch convert an entire directory
magick mogrify -format jxl -quality 80 *.png
# Resize and convert in one step
magick input.png -resize 1920x1080 -quality 82 output.jxl
Squoosh & GUI Tools
Google’s Squoosh web app includes a JPEG XL encoder, making it the easiest way to experiment with the format without installing anything. Drag in an image, select “JXL” as the output format, and adjust the quality slider.
For desktop use, XnView MP and IrfanView (with plugins) both support viewing and converting JXL files.
Batch Encoding Script
Here is a practical bash script for converting an entire image directory to JXL:
#!/bin/bash
# batch-encode-jxl.sh — Convert all images in a directory to JPEG XL
# Usage: ./batch-encode-jxl.sh /path/to/images [quality] [effort]
INPUT_DIR="${1:-.}"
QUALITY="${2:-80}"
EFFORT="${3:-7}"
OUTPUT_DIR="${INPUT_DIR}/jxl"
mkdir -p "$OUTPUT_DIR"
echo "Encoding images from $INPUT_DIR to JXL (quality=$QUALITY, effort=$EFFORT)"
find "$INPUT_DIR" -maxdepth 1 \( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' \) | while read -r file; do
filename=$(basename "$file")
base="${filename%.*}"
ext="${filename##*.}"
# Use lossless JPEG transcoding for JPEG inputs
if [[ "${ext,,}" == "jpg" || "${ext,,}" == "jpeg" ]]; then
echo " [JPEG lossless] $filename -> ${base}.jxl"
cjxl "$file" "$OUTPUT_DIR/${base}.jxl" --lossless_jpeg=1 -e "$EFFORT"
else
echo " [lossy q$QUALITY] $filename -> ${base}.jxl"
cjxl "$file" "$OUTPUT_DIR/${base}.jxl" -q "$QUALITY" -e "$EFFORT" --progressive
fi
done
echo "Done. Output in $OUTPUT_DIR"
JPEG XL for Archival & Photography
One of the most compelling and practical uses for jpeg xl today — independent of browser support — is archiving existing JPEG libraries. The lossless JPEG transcoding feature is unique to the jxl format and deserves a detailed walkthrough.
Understanding Lossless JPEG Transcoding
When you encode a JPEG into JPEG XL with --lossless_jpeg=1, the encoder does not decode the JPEG to pixels and re-encode. Instead, it restructures the existing DCT coefficients into JXL’s more efficient container. This means:
- Zero quality loss — not “visually lossless,” literally mathematically identical
- ~20% average size reduction — free storage savings
- Bitwise reversibility — you can reconstruct the original JPEG byte-for-byte with
djxl
Step-by-Step Archival Workflow
Step 1: Verify your source files
# Count JPEGs and total size
find /photos -iname '*.jpg' -o -iname '*.jpeg' | wc -l
find /photos -iname '*.jpg' -o -iname '*.jpeg' -exec du -cb {} + | tail -1
Step 2: Transcode to JXL (preserving directory structure)
#!/bin/bash
# archive-to-jxl.sh — Lossless JPEG-to-JXL archival with verification
SOURCE="/photos"
DEST="/photos-jxl"
find "$SOURCE" -iname '*.jpg' -o -iname '*.jpeg' | while read -r src; do
# Mirror directory structure
rel="${src#$SOURCE/}"
dest_dir="$DEST/$(dirname "$rel")"
base="$(basename "${rel%.*}")"
dest_file="$dest_dir/${base}.jxl"
mkdir -p "$dest_dir"
if [[ -f "$dest_file" ]]; then
echo "SKIP (exists): $rel"
continue
fi
echo "ENCODE: $rel"
cjxl "$src" "$dest_file" --lossless_jpeg=1 -e 7
done
Step 3: Verify roundtrip integrity
This is the critical step — confirm you can reconstruct the originals before deleting anything:
#!/bin/bash
# verify-roundtrip.sh — Confirm lossless transcoding is reversible
SOURCE="/photos"
JXL_DIR="/photos-jxl"
TEMP_DIR=$(mktemp -d)
FAILURES=0
find "$JXL_DIR" -iname '*.jxl' | head -100 | while read -r jxl; do
rel="${jxl#$JXL_DIR/}"
base="$(basename "${rel%.*}")"
orig_jpg="$SOURCE/$(dirname "$rel")/${base}.jpg"
if [[ ! -f "$orig_jpg" ]]; then
orig_jpg="$SOURCE/$(dirname "$rel")/${base}.jpeg"
fi
# Decompress JXL back to JPEG
djxl "$jxl" "$TEMP_DIR/roundtrip.jpg"
# Compare checksums
orig_hash=$(sha256sum "$orig_jpg" | cut -d' ' -f1)
rt_hash=$(sha256sum "$TEMP_DIR/roundtrip.jpg" | cut -d' ' -f1)
if [[ "$orig_hash" == "$rt_hash" ]]; then
echo "OK: $rel"
else
echo "FAIL: $rel (hashes differ)"
FAILURES=$((FAILURES + 1))
fi
done
rm -rf "$TEMP_DIR"
echo "Verification complete. Failures: $FAILURES"
Step 4: Measure savings
# Compare total sizes
echo "Original JPEGs:"
du -sh /photos
echo "JXL archive:"
du -sh /photos-jxl
For a typical photo library, expect 18-22% size reduction. On a 1 TB photo archive, that saves roughly 200 GB — with zero quality loss and full reversibility.
Why Photographers Should Care
For professional photographers and archivists, jpeg xl solves a real problem. RAW files are the gold standard for archival, but they are enormous. JPEGs are small but lossy. JPEG XL’s lossless transcoding gives you a smaller-than-JPEG archival format that preserves every bit of the original. If you ever need the JPEG back (for legacy software, client delivery, or print workflows), a single djxl command reconstructs it perfectly.
Implementation Strategies
Progressive Enhancement with <picture>
The <picture> element lets you offer multiple formats and the browser selects the first one it supports:
<picture>
<source srcset="image.jxl" type="image/jxl">
<source srcset="image.avif" type="image/avif">
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" alt="Description" loading="lazy">
</picture>
List formats from newest to oldest. Browsers that support JXL (Safari 17+) will select the first source. Others fall through to AVIF, WebP, or finally JPEG.
For responsive images, combine format sources with sizes and srcset:
<picture>
<source
srcset="image-400.jxl 400w, image-800.jxl 800w, image-1200.jxl 1200w"
sizes="(max-width: 600px) 400px, (max-width: 1000px) 800px, 1200px"
type="image/jxl"
>
<source
srcset="image-400.avif 400w, image-800.avif 800w, image-1200.avif 1200w"
sizes="(max-width: 600px) 400px, (max-width: 1000px) 800px, 1200px"
type="image/avif"
>
<img
src="image-800.jpg"
srcset="image-400.jpg 400w, image-800.jpg 800w, image-1200.jpg 1200w"
sizes="(max-width: 600px) 400px, (max-width: 1000px) 800px, 1200px"
alt="Description"
loading="lazy"
decoding="async"
>
</picture>
Using Image CDNs
CDNs like Sirv handle format negotiation automatically:
<img src="https://your-site.sirv.com/photos/sunset.jpg?format=optimal">
When browsers support JPEG XL, CDNs can serve it automatically without code changes. This is the lowest-friction path to adopting new formats — upload once, and the CDN converts and caches each format as needed. Sirv supports JPEG XL alongside AVIF, WebP, and legacy formats, detecting the optimal choice per request via the Accept header.
JPEG XL in Build Pipelines
Generating JXL files at build time ensures they are ready to serve without runtime encoding overhead. Here are practical configurations for popular frameworks.
Vite (with vite-plugin-image-optimizer)
// vite.config.js
import { defineConfig } from 'vite';
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer';
export default defineConfig({
plugins: [
ViteImageOptimizer({
jxl: {
quality: 80,
effort: 7,
progressive: true,
},
avif: {
quality: 65,
},
webp: {
quality: 80,
},
}),
],
});
Webpack (with image-minimizer-webpack-plugin)
// webpack.config.js
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
module.exports = {
optimization: {
minimizer: [
new ImageMinimizerPlugin({
generator: [
{
preset: 'jxl',
implementation: ImageMinimizerPlugin.sharpGenerate,
options: {
encodeOptions: {
jxl: {
quality: 80,
effort: 7,
},
},
},
},
{
preset: 'avif',
implementation: ImageMinimizerPlugin.sharpGenerate,
options: {
encodeOptions: {
avif: { quality: 65 },
},
},
},
],
}),
],
},
};
Astro (with astro-imagetools)
// astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
image: {
service: {
entrypoint: 'astro/assets/services/sharp',
config: {
// Sharp 0.33+ supports JXL output
jxl: {
quality: 80,
effort: 7,
},
},
},
},
});
In your Astro components, use the <Picture> component for multi-format output:
---
import { Picture } from 'astro:assets';
import heroImage from '../assets/hero.jpg';
---
<Picture
src={heroImage}
formats={['jxl', 'avif', 'webp']}
alt="Hero image"
widths={[400, 800, 1200]}
/>
Next.js (Custom Image Loader with Sharp)
Next.js does not natively output JXL from its image optimization pipeline yet, but you can generate JXL files at build time with a custom script:
// scripts/generate-jxl.mjs
import sharp from 'sharp';
import { glob } from 'glob';
import path from 'path';
import fs from 'fs';
const images = await glob('public/images/**/*.{jpg,jpeg,png}');
for (const imagePath of images) {
const outputPath = imagePath.replace(/\.(jpg|jpeg|png)$/i, '.jxl');
if (fs.existsSync(outputPath)) continue;
await sharp(imagePath)
.jxl({ quality: 80, effort: 7 })
.toFile(outputPath);
const original = fs.statSync(imagePath).size;
const compressed = fs.statSync(outputPath).size;
const savings = ((1 - compressed / original) * 100).toFixed(1);
console.log(`${path.basename(imagePath)} -> JXL (${savings}% smaller)`);
}
Add it to your build script in package.json:
{
"scripts": {
"prebuild": "node scripts/generate-jxl.mjs",
"build": "next build"
}
}
Server-Side JXL Detection
To serve JXL files efficiently, your server needs to detect client support via the Accept request header. Browsers that support jpeg xl include image/jxl in their Accept header.
Nginx Configuration
# /etc/nginx/conf.d/jxl.conf
map $http_accept $jxl_suffix {
default "";
"~image/jxl" ".jxl";
}
map $http_accept $avif_suffix {
default "";
"~image/avif" ".avif";
}
map $http_accept $webp_suffix {
default "";
"~image/webp" ".webp";
}
server {
listen 443 ssl;
server_name example.com;
location ~* ^(/images/.+)\.(jpg|jpeg|png)$ {
set $base $1;
set $ext $2;
# Try JXL first, then AVIF, then WebP, then original
add_header Vary Accept;
try_files $base$jxl_suffix $base$avif_suffix $base$webp_suffix $uri =404;
}
}
This configuration checks the Accept header, and if the browser signals JXL support, Nginx serves the .jxl file from the same directory. The Vary: Accept header is critical — it tells caches that the response depends on the Accept header, preventing a cached JXL from being served to a browser that cannot decode it.
Apache (.htaccess)
<IfModule mod_rewrite.c>
RewriteEngine On
# Serve JXL if supported and file exists
RewriteCond %{HTTP_ACCEPT} image/jxl
RewriteCond %{REQUEST_URI} (.+)\.(jpg|jpeg|png)$
RewriteCond %{DOCUMENT_ROOT}%1.jxl -f
RewriteRule (.+)\.(jpg|jpeg|png)$ $1.jxl [T=image/jxl,E=ORIGINAL_EXT:%2,L]
# Serve AVIF if supported and file exists
RewriteCond %{HTTP_ACCEPT} image/avif
RewriteCond %{REQUEST_URI} (.+)\.(jpg|jpeg|png)$
RewriteCond %{DOCUMENT_ROOT}%1.avif -f
RewriteRule (.+)\.(jpg|jpeg|png)$ $1.avif [T=image/avif,E=ORIGINAL_EXT:%2,L]
# Serve WebP if supported and file exists
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_URI} (.+)\.(jpg|jpeg|png)$
RewriteCond %{DOCUMENT_ROOT}%1.webp -f
RewriteRule (.+)\.(jpg|jpeg|png)$ $1.webp [T=image/webp,E=ORIGINAL_EXT:%2,L]
</IfModule>
<IfModule mod_headers.c>
# Add Vary header for proper caching
Header append Vary Accept env=ORIGINAL_EXT
</IfModule>
# Register MIME type
AddType image/jxl .jxl
CDN Configuration (Cloudflare / Generic)
Most CDNs can be configured to respect the Accept header for format selection. If your CDN supports edge workers or transform rules:
// Cloudflare Worker — format negotiation
addEventListener('fetch', (event) => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
const url = new URL(request.url);
const accept = request.headers.get('Accept') || '';
// Only process image requests
if (!/\.(jpg|jpeg|png)$/i.test(url.pathname)) {
return fetch(request);
}
const basePath = url.pathname.replace(/\.(jpg|jpeg|png)$/i, '');
// Try formats in order of preference
if (accept.includes('image/jxl')) {
const jxlResponse = await fetch(new URL(basePath + '.jxl', url.origin));
if (jxlResponse.ok) {
const response = new Response(jxlResponse.body, jxlResponse);
response.headers.set('Content-Type', 'image/jxl');
response.headers.set('Vary', 'Accept');
return response;
}
}
if (accept.includes('image/avif')) {
const avifResponse = await fetch(new URL(basePath + '.avif', url.origin));
if (avifResponse.ok) {
const response = new Response(avifResponse.body, avifResponse);
response.headers.set('Content-Type', 'image/avif');
response.headers.set('Vary', 'Accept');
return response;
}
}
// Fall through to original
return fetch(request);
}
Alternatively, using a CDN like Sirv eliminates the need for any server-side configuration. Sirv handles Accept header parsing, format encoding, caching, and delivery automatically.
Creating JPEG XL Images
Quality Guidelines
| Content Type | Quality | Effort | Notes |
|---|---|---|---|
| Photographs | 75-85 | 7 | Good balance of size and fidelity |
| E-commerce products | 80-88 | 7-8 | Preserve product details |
| Graphics/illustrations | 85-95 | 7 | Preserve sharp edges |
| Screenshots | 90-100 | 7 | Near-lossless for text clarity |
| Archival (from JPEG) | lossless_jpeg | 7 | Bitwise-reversible transcoding |
| Archival (from PNG/RAW) | 100 | 9 | Mathematically lossless, maximum compression |
| Thumbnails | 65-75 | 5 | Faster encoding, still good quality |
Migration Strategy
Phase 1: Preparation (Now)
Generate JXL alongside other formats in your build pipeline. This costs only disk space and build time — there is no risk, since no browser will receive a file it cannot decode if you use <picture> or server-side negotiation.
Start by adding JXL generation to your asset pipeline (see the build pipeline section above). Store generated JXL files alongside your existing AVIF and WebP variants.
Phase 2: Conditional Serving (Now)
Use <picture> with JXL as the first source. Safari 17+ users (a significant share of iOS traffic) will receive JXL files today, benefiting from smaller payloads and faster progressive loading.
If you use a CDN like Sirv, this phase requires zero code changes — the CDN automatically serves JXL to clients that support it.
Phase 3: Primary Format (Future)
When Chrome adds support (or if Firefox enables it by default), jpeg xl could become the primary format for the web. At that point, you could simplify your pipeline to generate only JXL and JPEG (as a legacy fallback), rather than maintaining four separate format variants.
The Future of JPEG XL
Despite the browser support challenges, the jpeg xl ecosystem continues to grow across multiple fronts.
Industry Adoption
Apple has been the strongest corporate backer. Beyond Safari, JPEG XL is supported natively in macOS, iOS, and visionOS at the system level. Apple’s Photos app, Preview, and Core Image framework all support the jxl format. This deep OS integration means third-party apps on Apple platforms get JXL support for free.
Adobe added JPEG XL support to Camera Raw and Lightroom. For the photography community, Adobe’s endorsement carries significant weight and validates JXL as a serious archival and editing format.
The Krita project and other open-source creative tools have added JXL support, giving artists and designers access to the format’s superior lossless compression for their working files.
Samsung has shown interest in JXL for its camera pipeline, and several Android camera apps now support JXL output.
Standardization Status
JPEG XL is formally standardized as ISO/IEC 18181 (Parts 1-4). This is a full international standard, not a draft or proposal. The specification covers the codestream format, file container, conformance testing, and reference software. This level of standardization provides long-term stability — the format will not change in backward-incompatible ways.
What Needs to Happen
For jpeg xl to reach its full potential as a web format, one critical thing needs to change: Chromium support. Chrome and Chromium-based browsers account for roughly 65% of global browser usage. Without them, JXL cannot become the default web image format.
The most likely paths forward:
- Mozilla ships JXL by default in Firefox. This would demonstrate that a major browser vendor sees value in the format and could pressure Google to reconsider.
- Apple mandates or strongly encourages JXL in App Store imagery. This would accelerate tooling and ecosystem development.
- Google reverses course. Community advocacy continues, and Google’s position could shift if enough ecosystem momentum builds independently of Chrome.
What You Should Do Today
Regardless of Chrome’s timeline, adopting jpeg xl today is a low-risk, high-reward strategy:
- Generate JXL files in your build pipeline alongside AVIF and WebP
- Serve conditionally using
<picture>elements or server-side content negotiation - Use JXL for archival — the lossless JPEG transcoding feature works now and saves real storage costs
- Choose a CDN like Sirv that handles format negotiation automatically, so you benefit from JXL support the moment any browser adds it
- Monitor browser support — the landscape could change rapidly once one more major browser commits
Conclusion
JPEG XL is technically superior to every current web image format. It delivers 50-60% smaller files than JPEG, offers lossless JPEG transcoding that no other format can match, provides native HDR support, and encodes faster than its closest competitor AVIF.
The main barrier remains browser support. Safari’s full adoption and Firefox’s behind-the-flag implementation are positive signals, but the jpeg xl chrome removal continues to limit widespread deployment. The jpeg xl vs avif question does not have a single answer — both formats have clear strengths, and the practical move is to generate and serve both.
For now, the winning strategy is straightforward:
- Generate JXL alongside other formats in your build pipeline
- Serve conditionally using
<picture>or server-sideAcceptheader negotiation - Use JXL for archival and photography workflows where it provides immediate, tangible benefits
- Monitor browser support for changes — the situation is evolving
- Use CDNs like Sirv that can add JXL support automatically, so your infrastructure is ready the moment the format goes mainstream