本文へ移動
WEB 制作・集客

JPEG XL を足すか決める。AVIF・WebP との使い分けと、picture・Accept で安全に入れる手順

公開 読了まで 約17分

( この記事の要点 )

  1. JPEG XL は AVIF・WebP の置き換えではなく、既存の JPEG を画質を変えずに小さくでき、元に戻せるのが強み。足すかは画像の資産と配信の仕組みで決める
  2. picture の先頭に source type="image/jxl" を足せば、対応しないブラウザは飛ばして次の形式を使うので、段階的に入れられる
  3. Accept で出し分けるなら Vary: Accept が必須。Safari にも JPEG XL が届くのでアニメーション画像は対象から外す。Next.js の組み込みの画像最適化は JPEG XL を出せない

「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 とキャッシュの注意を、手元で動かしたコードと一緒にまとめます。

2026年10月に何が変わったか(2026年11月時点)

ブラウザの対応や道具の仕様は変わりやすいので、この節にまとめます。

ブラウザ・道具 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 はない

いくつか補足します。

  • Chrome は2026年9月から2週間ごとのリリースに移っています。「Chrome 155 以降」と考えてください。
  • Safari の「部分対応」について、WebKit の Safari 17.0 の記事はプログレッシブな読み込みを長所に挙げていて、caniuse の注記と食い違います。少なくともアニメーションの JPEG XL は使わない、と決めておけば安全です。また WebKit のバグ報告によると、macOS Ventura・Monterey 上の Safari 17 では JPEG XL が無効にされています。
  • Edge は、リリースノートの記述とは別に、Edge 155 で表示できなかったという報告(PiunikaWeb)もあります。Edge の利用者が多いサイトでは、実機で表示と Network パネルの 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%小さい」と書いていますが、どちらも比べた条件までは書かれていません。数字は自社の画像で測ってから判断してください。

素材ごとに任せる形式の図。見出しは「素材」「任せる形式」。「既存の JPEG(過去の写真)」から「JPEG XL(可逆で再圧縮)」へ矢印があり、逆向きの濃い水色の矢印に「戻せる」。「新しい写真(これから作る)」から「AVIF(主力)」へ。「対応しない環境」から「WebP・JPEG(受け皿)」へ。
形式ごとの役割の目安。既存の JPEG は JPEG XL で可逆に再圧縮でき、元の JPEG に戻せる。新しい写真は AVIF、AVIF も使えない環境の受け皿は WebP と JPEG(説明用の図です)

判断の目安は次のとおりです。

  • 足す価値が高い:写真の JPEG が大量にあり(EC の商品画像、メディアの過去記事など)、作り直さずに転送量を減らしたい。
  • 様子見でよい:画像の多くが AVIF で十分に小さく、ビルドの時間をこれ以上増やしたくない。
  • 足さない:アニメーション画像が中心(Safari が非対応)。配信の仕組みが Next.js の組み込みの画像最適化だけで完結している。

<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>
「上から順に見て、最初に合ったものを使う」「例:JPEG XL に対応しないブラウザ」。下向きの矢印のそばに4行。「source jxl」は取り消し線で「未対応 → 飛ばす」。「source avif」は濃い水色の枠で「これを使う」。「source webp」と「img jpg」は「見ない」。
picture の source は上から順に調べられ、type に対応していなければ飛ばされる。最初に合ったものが使われ、それより下は使われない(説明用の図です)

書くときのポイントです。

  • 上から順に、最初に条件が合ったものが使われます。 優先したい形式を上に置きます。
  • 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 で破綻しないことが確かめられます。

Accept で出し分けるときは Vary とキャッシュに注意

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つあります。

  1. Chrome と Firefox で並び順が違い、q 値の差もありません。 並び順に意味を持たせず、返す順はサーバーで決めます。
  2. Safari 17 以降の Accept にも image/jxl が入ります。 Accept で出し分けると Safari にも JPEG XL が届きます。Safari はアニメーションの JPEG XL に対応していないので、アニメーション画像は出し分けの対象から外します。
  3. 応答に Vary: Accept が必須です。 これがないと、CDN やプロキシなどの共有キャッシュが、JPEG XL に対応したブラウザ向けの応答を、対応していないブラウザ(たとえば JPEG XL が無効の古い Chrome)に返すことがあります。
上は「NG」「Vary なし」。CDN のキャッシュは「キー:URL だけ」で、ラベル「形式を区別しない」。中身は .jxl だけで、「jxl 対応 ブラウザ」にも「jxl 非対応 ブラウザ」にも .jxl が返り、非対応のほうは「表示できない」。下は「OK」「Vary: Accept」。キャッシュは「キー:URL+形式」で .jxl・.avif・.jpg に分かれ、ラベル「少数の形式に丸める」。対応のブラウザには .jxl、非対応のブラウザには .avif が返り「表示できる」。
Vary: Accept がないと、CDN は URL だけをキーにして、JPEG XL を非対応のブラウザにも返してしまう。Vary: Accept を付けたうえで、CDN の設定でキーを少数の形式に丸めると正しく分かれる(説明用の図です)

次のコードは、考え方を確かめるための最小の例です(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 やサーバーの機能に任せることが多いはずです。そのときに確かめることです。

  • キャッシュのキーを少数にまとめる。 Accept の文字列はブラウザや版ごとに違うので、そのまま Vary のキーにするとキャッシュが細かく分かれます。「jxl / avif / webp / jpeg」の4つ程度に丸めてからキーにできるかを、CDN の設定で確かめます。
  • CDN の対応する拡張子を見る。 たとえば Cloudflare の Vary for images は、対象の拡張子の一覧に .jxl がありません。
  • Next.js の組み込みの画像最適化は JPEG XL を出せません。 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 もセキュリティ修正のため新しい版への更新を勧めています)。

まとめ:足す前のチェックリスト

  • □ 既存の JPEG が多く、再圧縮の効果が見込めるか(自社の画像で測ったか)
  • □ <picture> で出すか、Accept で出し分けるかを決めたか
  • □ <picture> なら、<source type="image/jxl"> を先頭に置き、<img> に alt・width・height があるか
  • □ Accept なら、Vary: Accept を付け、CDN のキャッシュのキーと対応する拡張子を確かめたか
  • □ アニメーション画像を JPEG XL にしていないか(Accept で出し分ける場合も対象から外したか)
  • □ Safari と Edge の実機で、表示と Content-Type を確かめたか
  • □ OGP など、ブラウザ以外が読む画像を対象から外したか

画像の形式は、ブラウザの対応がそろうたびに選び直すことになります。最初に「どの形式に何を任せるか」と「どの仕組みで出すか」を決めておけば、次の形式が来ても、<source> を1行足すかどうかの判断で済みます。

MODS BASE では、WEB サイトの制作と運用の中で、画像の配信の見直しもお手伝いしています。気になることがあれば、お気軽にご相談ください。

( Written by )

MODS BASE

MODS BASEは、長野県上伊那郡辰野町を拠点に、WEB 制作、WEB 集客の運用代行、UI/UX デザイン・プロダクト開発、ブランディング・グラフィック、AI 導入支援を手がけるデザイン・開発スタジオです。全国のお客様にオンラインで対応しています。

( Related service )

WEB 制作

何を伝え、どう動いてもらうか。UX の設計から考えるホームページ制作。

( Related )

関連記事

( Contact )

Let’s talk.

まだ決まっていなくても大丈夫です。気になっていることから、気軽にお聞かせください。