
AI 活用
公開 読了まで 約17分

「JPEG XL が Chrome でも表示できるようになったらしい。うちの画像にも足したほうがいい?」。2026年10月、Chrome 155 と Firefox 158 で JPEG XL(拡張子 .jxl、MIME タイプ image/jxl)が既定で有効になり、そう聞かれる場面が増えてきました。
結論から書くと、JPEG XL は「AVIF・WebP を置き換えるもの」ではなく、<picture> の先頭に足せる選択肢の1つです。足すかどうかは、画像の資産(既存の JPEG がどれだけあるか)と、配信の仕組み(<picture> か、Accept ヘッダーでの出し分けか)で決まります。この記事では、形式の使い分けの基準、<picture> での入れ方、Accept で出し分けるときの Vary とキャッシュの注意を、手元で動かしたコードと一緒にまとめます。
ブラウザの対応や道具の仕様は変わりやすいので、この節にまとめます。
| ブラウザ・道具 | JPEG XL の状況(2026年11月時点) |
|---|---|
| Chrome | 155 から対応(安定版の予定日 2026-10-06)。Rust 製のデコーダー jxl-rs を使う |
| Firefox | 158 で既定で有効に(2026-10-13 リリース)。画像の Accept に image/jxl が入った |
| Safari | 17.0 から対応。caniuse では「部分対応」(静止画のみでアニメーションは非対応、プログレッシブなデコードは非対応と注記) |
| Edge | 情報が食い違う。Microsoft の Edge 155 のリリースノートは「対応」、caniuse と web.dev は「非対応」 |
| Baseline | 対象外(web-features の jpegxl は baseline: false)。AVIF と WebP は Baseline Widely available |
| Next.js の組み込みの画像最適化 | images.formats で選べるのは image/avif と image/webp(JPEG XL は選べない) |
| Cloudflare の Vary for images | Pro 以上のプラン。対象の拡張子の一覧に .jxl はない |
いくつか補足します。
Content-Type を確かめてから広げてください。ここからは、ブラウザの版が進んでも使える考え方です。まず、各形式に「何を任せるか」を決めます。
| 形式 | 任せること | 注意 |
|---|---|---|
| JPEG | 最後の受け皿。SNS のクローラーなど、ブラウザ以外が読む画像 | 単体ではいちばん重い |
| WebP | AVIF が使えない環境への受け皿 | 主力にするなら、自社の画像で AVIF と大きさを比べてから |
| AVIF | 新しく作る写真・イラストの主力 | エンコードの設定によっては、ビルドの時間に響く |
| JPEG XL | 既存の JPEG の再圧縮、大きな写真、HDR | Baseline ではない。対応しないブラウザには別の形式が要る |
JPEG XL にしかない強みは、既存の JPEG を画質を変えずに小さくでき、元の JPEG にそのまま戻せることです(jpeg.org の説明)。WebKit は、この再圧縮で平均20%小さくなると書いています。新しく圧縮する場合について、Google は「JPEG より30〜50%よい圧縮」、WebKit は「最大60%小さい」と書いていますが、どちらも比べた条件までは書かれていません。数字は自社の画像で測ってから判断してください。

判断の目安は次のとおりです。
<picture> の type で段階的に入れるいちばん安全なのは、<picture> の先頭に <source type="image/jxl"> を足す方法です。HTML の仕様では、type が未知または未対応の MIME タイプの <source> は飛ばされ、次の <source> が調べられます。対応していないブラウザは何も読み込まずに次へ進むので、むだな通信も起きません。
<picture>
<source srcset="/images/hero.jxl" type="image/jxl">
<source srcset="/images/hero.avif" type="image/avif">
<source srcset="/images/hero.webp" type="image/webp">
<img src="/images/hero.jpg" alt="(画像の説明)" width="1200" height="800" decoding="async">
</picture>

書くときのポイントです。
alt・width・height は <img> に書きます。どの形式が選ばれても <img> の要素が表示を受け持つので、ここに書けば全部に効きます。srcset に幅の違う画像を並べるときは、どの <source> にも同じ sizes を付けます。.jxl を Content-Type: image/jxl で返すかを curl -I で確かめます。設定に .jxl がないと、別の型で返ることがあります。手元では、Playwright の Chromium 153(JPEG XL がまだ既定で無効の版)でこの HTML を開きました。既定では AVIF が選ばれ、--enable-features=JXLImageFormat を付けて起動すると JPEG XL が選ばれて表示されました。対応・非対応のどちらでも、同じ HTML で破綻しないことが確かめられます。
HTML を変えずに、同じ URL(例:/images/hero.jpg)で形式を出し分ける方法もあります。ブラウザが画像の要求に付ける Accept ヘッダーを見て、サーバーが返す形式を選びます。
| ブラウザ | 画像の要求の Accept(出典の値) |
|---|---|
| Chrome(JPEG XL が有効なとき) | image/jxl,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8 |
| Firefox 158 | image/avif,image/jxl,image/webp,image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5 |
| Safari 17 以降 | image/webp,image/avif,image/jxl,image/heic,image/heic-sequence,video/*;q=0.8,image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5 |
Chrome の値は Chromium のソース(2026年11月時点の main)にある文字列で、手元の Chromium 153 でも、JPEG XL を有効にして起動すると同じ値が送られました。Safari の値は、Mozilla の Bugzilla に記録された Safari 17.4(Technology Preview)の値です。お使いの Safari の実際の値は、Web インスペクタの Network で確かめてください。MDN の既定の Accept の一覧は、Chrome の行が 121 時点、Safari の行が macOS Big Sur 時点の値(どちらも jxl なし)のままなので注意してください。
この表から分かることが3つあります。
image/jxl が入ります。 Accept で出し分けると Safari にも JPEG XL が届きます。Safari はアニメーションの JPEG XL に対応していないので、アニメーション画像は出し分けの対象から外します。Vary: Accept が必須です。 これがないと、CDN やプロキシなどの共有キャッシュが、JPEG XL に対応したブラウザ向けの応答を、対応していないブラウザ(たとえば JPEG XL が無効の古い Chrome)に返すことがあります。
次のコードは、考え方を確かめるための最小の例です(Node.js 22、依存なし)。/images/hero.jpg への要求に対して、hero.jxl・hero.avif・hero.webp のうち Accept に入っていて、ファイルがあるものを上から選びます。
// Node.js 22(依存なし)。/images/*.jpg への要求に、Accept を見て形式を選んで返す
import { createServer } from "node:http";
import { readFile, access } from "node:fs/promises";
import path from "node:path";
const ROOT = path.resolve("public");
// 返す順はサーバーで決める(Accept の並び順には頼らない)
const FORMATS = [
{ type: "image/jxl", ext: ".jxl" },
{ type: "image/avif", ext: ".avif" },
{ type: "image/webp", ext: ".webp" },
];
// Accept に type が入っていて、q=0 で拒否されていなければ true
function accepts(accept, type) {
return accept.split(",").some((part) => {
const [mime, ...params] = part.trim().split(";").map((s) => s.trim());
const q = params.find((p) => p.toLowerCase().startsWith("q="));
return mime.toLowerCase() === type && (q === undefined || Number(q.slice(2)) > 0);
});
}
const exists = (f) => access(f).then(() => true, () => false);
createServer(async (req, res) => {
const { pathname } = new URL(req.url, "http://localhost");
const jpg = path.join(ROOT, path.normalize(pathname));
if (!jpg.startsWith(ROOT + path.sep) || !jpg.endsWith(".jpg")) {
res.writeHead(404).end();
return;
}
let file = jpg;
let type = "image/jpeg";
for (const f of FORMATS) {
const alt = jpg.slice(0, -4) + f.ext;
if (accepts(req.headers.accept ?? "", f.type) && (await exists(alt))) {
file = alt;
type = f.type;
break;
}
}
try {
const body = await readFile(file);
res.writeHead(200, {
"Content-Type": type,
"Vary": "Accept", // Accept によって中身が変わることをキャッシュに伝える
"Cache-Control": "public, max-age=86400",
});
res.end(body);
} catch {
res.writeHead(404).end();
}
}).listen(8080);
表の3つの Accept で curl から試すと、どれにも image/jxl が返りました。image/jxl を含まない Accept(たとえば JPEG XL が無効の Chrome の値)には image/avif が返ります。image/jxl;q=0 を付けた要求には AVIF が、Accept なしの要求には JPEG が返ります。
本番では、この処理を CDN やサーバーの機能に任せることが多いはずです。そのときに確かめることです。
Vary のキーにするとキャッシュが細かく分かれます。「jxl / avif / webp / jpeg」の4つ程度に丸めてからキーにできるかを、CDN の設定で確かめます。images.formats で選べるのは AVIF と WebP で、Accept を見て形式を選び、形式ごとに別々にキャッシュします。前にプロキシを置くなら、Accept を転送する設定が要ります。独自の loader で画像 CDN に任せる場合は、その CDN の対応次第です。組み込みの最適化のまま JPEG XL を足したい画像は、ビルド時に作って <picture> で出すのが現実的です。既存の JPEG を再圧縮するには、libjxl の cjxl を使います。JPEG を入力すると、既定で可逆の再圧縮になります。版によって既定が変わっても困らないように、オプションで明示しておくと安心です。
# 既存の JPEG を可逆に再圧縮する
cjxl hero.jpg hero.jxl --lossless_jpeg=1
# 元の JPEG に戻して、1バイトも変わっていないかを確かめる
djxl hero.jxl restored.jpg
sha256sum hero.jpg restored.jpg
手元(Ubuntu 24.04 のパッケージの libjxl 0.7.0)で試したところ、2つのハッシュは一致しました。1200×800 の試験用の画像(写真ではなく合成した絵)では、85.7KB の JPEG が 63.1KB(約26%減)になりました。原本を JPEG XL だけにしても、必要なときに元の JPEG を作り直せます。ただし、配信用の .jpg は受け皿として残してください。Ubuntu 24.04 のパッケージは古い版なので、本番の変換には最新の libjxl を使ってください(libjxl の README もセキュリティ修正のため新しい版への更新を勧めています)。
<picture> で出すか、Accept で出し分けるかを決めたか<picture> なら、<source type="image/jxl"> を先頭に置き、<img> に alt・width・height があるかVary: Accept を付け、CDN のキャッシュのキーと対応する拡張子を確かめたかContent-Type を確かめたか画像の形式は、ブラウザの対応がそろうたびに選び直すことになります。最初に「どの形式に何を任せるか」と「どの仕組みで出すか」を決めておけば、次の形式が来ても、<source> を1行足すかどうかの判断で済みます。
MODS BASE では、WEB サイトの制作と運用の中で、画像の配信の見直しもお手伝いしています。気になることがあれば、お気軽にご相談ください。
MODS BASE
MODS BASEは、長野県上伊那郡辰野町を拠点に、WEB 制作、WEB 集客の運用代行、UI/UX デザイン・プロダクト開発、ブランディング・グラフィック、AI 導入支援を手がけるデザイン・開発スタジオです。全国のお客様にオンラインで対応しています。
( Related )