画像圧縮 完全戦略 2025 ─ 画質を守りつつ体感速度を最適化する実践ガイド
公開: 2025年9月16日 · 読了目安: 3 分 · 著者: Unified Image Tools 編集部
本記事の目的は、画質を保ちつつファイルサイズを抑え、LCP/INP を含む体感速度を安定的に改善する「実務に使える圧縮・配信」設計の要点を、最短で把握できる形でまとめることです。
TL;DR
- まずはリサイズ、次に品質調整。最大幅の見直しだけで 30–70% 減ることが多い。
- 写真は WebP/AVIF、UI/ロゴは PNG/WebP(ロスレス)。透過が不要なら JPEG/WebP/AVIF のほうが軽い。
- レスポンシブ配信と遅延読み込みを徹底。LCP 画像はプリロード/優先度付け。
- 再圧縮の連鎖は厳禁。高品質マスターを保持し、変換はワンパスで完結。
- 自動化: CI/ビルドでプリセット適用、配信は長期キャッシュ + 指紋付け。
画像圧縮の基本原理
転送コストは、「ピクセル数 × エンコード効率」でほぼ決まります。まずピクセル(面積)を減らす=リサイズ、その後でフォーマット/品質を詰めます。
優先度の目安:
- 最大幅/高さの制約(レイアウトに見合う最小値)
- フォーマット選択(写真/UI/透過の有無)
- 品質/サブサンプリング/色空間などの微調整
フォーマット選択の実務指針
- 写真: 互換性重視なら WebP、最小サイズ重視なら AVIF を試す。
- UI/ロゴ/アイコン: 透過とエッジ保全のため PNG か WebP(ロスレス)。
- 透過不要の写真: JPEG から WebP/AVIF への移行で大幅削減。
運用のポイント(チェックリスト)
- 解像度の過剰配信をしない(srcset/sizes を設定)
- LCP 対象はプリロードし fetchpriority を適切化
- 長期キャッシュ + 指紋付け(name.hash.ext)
- 画質破綻の早期検知(テキストのにじみ、バンディング、ICC の扱い)
次のアクション
- まずは 3 ステップ: リサイズ → フォーマット選び → 品質微調整
- その後、レスポンシブ配信と遅延読み込みで無駄転送を削減
- CI/ビルドに取り込み、配信を安定化
まず「KPI」を定義する(CWV と業務要件)
重要: 画像最適化は「何のために」「どこまで」やるのかを最初に決めると迷いません。
- Core Web Vitals: LCP 画像の遅延を減らす、INP を悪化させないよう遅延読みやプレースホルダを工夫する。
- ビジネス要件: クリエイティブの再現性(ブランド色、肌色)、CMS/生成パイプラインの自動化、配信コスト。
- 運用負債の最小化: 変換はワンパス、マスター原稿を保持、フォーマット判定を自動化。
「速さ」と「綺麗さ」を両立させるには、LCP 対象のサイズ削減と、劣化が目立つ要素(文字、肌色、グラデーション)の破綻回避が鍵です。
画像サイズ戦略(レイアウトから逆算)
- レイアウトごとに「最大表示幅」を決める(コンテナ幅 × 端末 DPR)。例: 768px カラム × DPR 2 → 1536px を上限。
- 余白や角丸などの装飾により実効描画領域が狭まる場合、さらに小さくできることが多い。
- ベクター化できる要素(単色ロゴ、シンプルな図)は SVG 化を検討。
上限ピクセル = min(コンテナ幅, ビューポート幅) × 想定DPR
フォーマット判定の思考プロセス
- 透過が必要か? → 必要なら PNG/WebP ロスレス。
- 写真かイラストか? → 写真なら WebP/AVIF。イラストは WebP ロスレスや PNG。
- 互換性第一か容量最小か? → 幅広い互換性: WebP、最小容量: AVIF。
- LCP 対象か? → デコード時間を見ながら品質(q)を調整、プリロード付与。
実務では「WebP をベースに AVIF をテストし、劣化(輪郭/肌/グラデ)が気にならなければ AVIF 採用」という流れが扱いやすいです。
最小構成の自動変換(Node.js / sharp)
MD/ブログなど軽量サイトでも使える、最低限のビルドスクリプト例です。
// scripts/build-images.ts
import sharp from 'sharp'
import { readdirSync, mkdirSync, existsSync } from 'node:fs'
import { join, basename, extname } from 'node:path'
const SRC = 'assets/images'
const OUT = '.dist/images'
const WIDTHS = [640, 960, 1280, 1536, 1920]
if (!existsSync(OUT)) mkdirSync(OUT, { recursive: true })
for (const file of readdirSync(SRC)) {
const input = join(SRC, file)
const name = basename(file, extname(file))
for (const w of WIDTHS) {
const pipeline = sharp(input).resize({ width: w, withoutEnlargement: true })
await pipeline.webp({ quality: 78 }).toFile(join(OUT, `${name}-${w}.webp`))
await pipeline.avif({ quality: 58 }).toFile(join(OUT, `${name}-${w}.avif`))
}
}
ポイント:
- WebP q≈75–80、AVIF q≈50–60 から開始。輪郭や肌で破綻があれば +5 ずつ上げる。
- 拡大禁止(withoutEnlargement)で無駄な計算と容量を抑止。
Next.js での配信(next/image と優先度)
// 例: LCP 対象ヒーロー画像(概念的サンプル)
// import Image from 'next/image'
// export default function Hero() {
// return (
// <Image
// src="/hero-1536.avif"
// alt="プロダクトヒーロー"
// width={1536}
// height={864}
// sizes="(max-width: 768px) 100vw, 768px"
// priority
// fetchPriority="high"
// placeholder="blur"
// blurDataURL="data:image/webp;base64,...."
// />
// )
// }
ベストプラクティス:
- LCP 対象のみ
priority
/fetchPriority="high"
を付与。 sizes
を正しく設定して過剰解像度を防止。- 可能なら
preload
を<link rel="preload" as="image">
で追加。
CLI 派のための簡易レシピ
# WebP 変換(cwebp)
cwebp input.jpg -q 78 -m 6 -mt -o out.webp
# AVIF 変換(avifenc / libaom)
avifenc --min 28 --max 32 --speed 6 input.png out.avif
# まとめてリサイズ(ImageMagick)
magick input.jpg -resize 1536x -quality 85 out-1536.jpg
品質検証(人間の目 + 指標)
- 肉眼での確認: 文字のにじみ、髪の毛のざらつき、肌色の変色、グラデのバンディング。
- 指標の併用: SSIM/PSNR だけでなく ΔE00(色差)やエッジ差分を参考にする。
簡易 ΔE 平均値の概算スクリプト例(厳密でなく傾向把握用):
// scripts/diff-mean.ts
import sharp from 'sharp'
function dE(a, b) {
// 簡易 CIEDE2000 ではなく、ここでは Lab の距離で概算
const [L1, a1, b1] = a, [L2, a2, b2] = b
const dL = L1 - L2, da = a1 - a2, db = b1 - b2
return Math.sqrt(dL * dL + da * da + db * db)
}
const src = process.argv[2]
const tgt = process.argv[3]
const A = await sharp(src).toColorspace('lab').raw().ensureAlpha().toBuffer({ resolveWithObject: true })
const B = await sharp(tgt).toColorspace('lab').raw().ensureAlpha().toBuffer({ resolveWithObject: true })
if (A.info.width !== B.info.width || A.info.height !== B.info.height) throw new Error('size mismatch')
let sum = 0; let n = 0; const p = A.buffer; const q = B.buffer
for (let i = 0; i < A.buffer.length; i += 4) {
const lab1 = [p[i], p[i + 1], p[i + 2]]
const lab2 = [q[i], q[i + 1], q[i + 2]]
sum += dE(lab1, lab2); n++
}
console.log('meanΔE(lab-dist approx)=', (sum / n).toFixed(2))
しきい値の目安:
- meanΔE ≈ 1.0 付近 → ほぼ見分けがつかないケースが多い。
- meanΔE ≈ 2.0 超 → 髪・肌・グラデで違和感が出やすい。q を上げる/ロスレスへ。
CDN/キャッシュ設計(最低限の型)
- Cache-Control: public, max-age=31536000, immutable
- ETag/Last-Modified: 適宜
- ファイル名: name.hash.ext (指紋付け)
静的画像は長期キャッシュ + 指紋付け。ダイナミック変換は stale-while-revalidate
を組み合わせて再生成コストを平準化します。
よくある落とし穴(デバッグの勘所)
- ICC プロファイルの欠落/変換ミス → sRGB へ統一。
- サブサンプリングの目視劣化 → 文字/UI は 4:4:4(サブサンプル無し)で書き出す。
- 再圧縮の連鎖 → 元の JPEG を再エンコードすると破綻が蓄積。必ずマスターからワンパス。
- 透過の不要な PNG → WebP/AVIF に置き換えると劇的に軽量化。
FAQ(よくある質問)
- Q. AVIF は常に WebP より良いですか?
- 画像によります。写真では AVIF が小さくなることが多い一方、複雑なテクスチャやエッジで破綻が目立つ場合は WebP の方が安定します。まず WebP、次いで AVIF を評価する二段構えを推奨します。
- Q. 画質と容量の落としどころは?
- LCP 対象は体感速度を最優先に q をやや攻め気味に。ブランド色/肌色が目立つビジュアルは q を高め、UI はロスレス/4:4:4 を選ぶなど、役割別に最適点を変えます。
- Q. 既存の JPEG 資産はどう扱うべき?
- Q. Next.js の画像最適化と自前ビルド、どちらが良い?
- トラフィックが大きいなら事前ビルド + CDN、更新頻度が高いなら on-demand 変換 + キャッシュの二段構えが現実的です。
まとめ(実務フローの雛形)
-
レイアウトから最大幅を決める → まずリサイズ。
-
フォーマット判定: WebP 基本 + AVIF 試験、UI/ロゴはロスレス。
-
品質チューニング: 目視 + 簡易指標(meanΔE/SSIM)で q を詰める。
-
sizes/srcset
を整備し、LCP は priority/preload。 -
ビルドへ組み込み、長期キャッシュ + 指紋付けで配信安定化。
// ...copied content from the original file...
関連記事
フォーマット変換の戦略 2025 — WebP/AVIF/JPEG/PNG を使い分ける指針
コンテンツ種別ごとの意思決定と運用フロー。互換性・容量・画質のバランスを取り、最小の労力で安定化。
正しいカラー管理とICCプロファイル戦略 2025 ─ Web画像の色再現を安定させる実践ガイド
デバイスやブラウザ間で色ズレを起こさないためのICCプロファイル/カラースペース/埋め込み方針と、WebP/AVIF/JPEG/PNG各形式における最適化手順を体系化。
画像最適化の基本 2025 — 勘に頼らない土台づくり
どのサイトにも効く、速くて美しい配信のための最新ベーシック。リサイズ→圧縮→レスポンシブ→キャッシュの順で安定運用に。
画像SEO 2025 — alt・構造化データ・サイトマップの実務
検索流入を逃さない画像SEOの最新実装。altテキスト/ファイル名/構造化データ/画像サイトマップ/LCP最適化を一つの方針で整えます。
2025年のレスポンシブ画像設計 — srcset/sizes 実践ガイド
ブレークポイントとカード密度から逆算して、srcset/sizes を正しく書くための決定版チートシート。LCP、アートディレクション、アイコン/SVG の扱いまで網羅。
アクセシビリティ実務の画像 — alt/装飾/図解の線引き 2025
スクリーンリーダーで破綻しない画像の実装。装飾は空alt、意味画像は簡潔に、図解は本文を要約。リンク画像とOGPの注意点も。