JA EN

画像読み込みエラーのハンドリングベストプラクティス - フォールバックと UX 改善

· 約 9 分で読めます

画像読み込みエラーの種類と原因 - なぜ画像は表示されないのか

Web ページで画像が表示されない原因は多岐にわたります。適切なエラーハンドリングを実装するためには、まずエラーの種類を理解する必要があります。

主なエラー原因:

エラーの影響: 画像エラーを放置すると、ブラウザはデフォルトの壊れた画像アイコン (破れた画像マーク) を表示します。これはユーザーに「サイトが壊れている」という印象を与え、信頼性を損ないます。特に EC サイトの商品画像やプロフィール画像が表示されない場合、コンバージョン率に直接影響します。

HTTP Archive の調査によると、Web ページの画像リクエストの約 3-5% がエラーを返しています。100 枚の画像があるページでは、3-5 枚が表示されない計算です。この数字は無視できるものではなく、適切なフォールバック戦略が必要です。

onerror イベントによる基本的なフォールバック実装

HTML の <img> 要素は、画像の読み込みに失敗すると error イベントを発火します。このイベントをハンドリングすることで、フォールバック画像への切り替えやプレースホルダーの表示が可能です。

インラインでのフォールバック:

<img src="product.jpg" onerror="this.src='/images/fallback.png'; this.onerror=null;" alt="商品画像">

this.onerror=null は重要です。フォールバック画像も読み込みに失敗した場合、無限ループを防止します。これがないと、フォールバック画像のエラーが再度 onerror を発火し、永遠にリクエストが繰り返されます。

JavaScript での実装:

document.querySelectorAll('img').forEach(img => {
img.addEventListener('error', function() {
this.src = '/images/fallback.svg';
this.classList.add('img-error');
this.removeEventListener('error', arguments.callee);
});
});

React での実装:

function ImageWithFallback({ src, fallback, alt }) {
const [imgSrc, setImgSrc] = useState(src);
const [hasError, setHasError] = useState(false);
return (
<img src={hasError ? fallback : imgSrc}
onError={() => { setHasError(true); }}
alt={alt} />
);
}

注意点: onerror は画像の HTTP レスポンスがエラーの場合だけでなく、デコードに失敗した場合にも発火します。また、src 属性が空文字列の場合は error イベントが発火しないブラウザもあるため、空の src は避けてください。

フォールバック画像の設計 - 用途別の最適なアプローチ

フォールバック画像は「画像が表示できない」ことをユーザーに伝えつつ、ページの見た目を大きく損なわないデザインが求められます。用途に応じた最適なフォールバックを設計します。

汎用フォールバック (SVG 推奨): サイト全体で使用する汎用的なフォールバック画像は、SVG で作成することを推奨します。SVG はどのサイズでもシャープに表示され、ファイルサイズも小さい (通常 1KB 未満) ため、追加のネットワークリクエストの負荷が最小限です。

<svg viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg">
<rect fill="#f0f0f0" width="400" height="300"/>
<text x="200" y="150" text-anchor="middle" fill="#999">Image</text>
</svg>

ユーザーアバター用フォールバック: プロフィール画像が読み込めない場合は、ユーザーのイニシャルを表示する CSS ベースのフォールバックが効果的です。背景色をユーザー名のハッシュから生成すれば、ユーザーごとに異なる色のアバターが表示されます。

商品画像用フォールバック: EC サイトでは「画像準備中」のプレースホルダーを表示し、商品情報 (名前、価格) は引き続き表示することで、ユーザーの購買行動を妨げません。カテゴリごとに異なるフォールバック画像 (衣類のシルエット、電子機器のアイコンなど) を用意すると、より親切です。

Data URI によるインラインフォールバック: 外部ファイルへのリクエストすら失敗する可能性がある場合 (オフライン環境など)、Base64 エンコードした SVG を Data URI として直接埋め込む方法が最も確実です。

const FALLBACK = 'data:image/svg+xml;base64,PHN2ZyB...';

CSS によるエラー状態のスタイリング - 壊れた画像を美しく隠す

CSS だけで画像エラー時の表示を改善する方法があります。JavaScript が無効な環境でも動作するため、プログレッシブエンハンスメントの観点から有効です。

壊れた画像アイコンを隠す: 画像の読み込みに失敗すると、ブラウザは alt テキストと壊れた画像アイコンを表示します。以下の CSS で、エラー時にカスタムスタイルを適用できます。

img {
font-family: sans-serif;
font-size: 0.875rem;
color: #666;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
}

::before と ::after 疑似要素の活用: 画像が正常に読み込まれた場合、::before::after 疑似要素は表示されません。しかし、読み込みに失敗した場合はこれらの疑似要素が有効になります。この特性を利用して、エラー時のみカスタムコンテンツを表示できます。

img::before {
content: '';
display: block;
position: absolute;
inset: 0;
background: #f5f5f5;
}
img::after {
content: attr(alt) ' (画像を読み込めませんでした)';
display: block;
position: absolute;
inset: 0;
padding: 1rem;
background: #f9f9f9;
border: 1px dashed #ddd;
}

注意点: 疑似要素による方法はブラウザ間で挙動が異なります。Chrome と Firefox では動作しますが、Safari では <img> の疑似要素がサポートされていない場合があります。クロスブラウザ対応が必要な場合は、JavaScript による onerror ハンドリングと併用してください。

object-fit との組み合わせ: object-fit: cover を使用している画像がエラーになった場合、フォールバック画像にも同じ object-fit が適用されます。フォールバック画像のアスペクト比が異なる場合に意図しないクロッピングが発生しないよう、フォールバック画像は正方形で作成することを推奨します。

リトライ戦略とプログレッシブローディング - 一時的なエラーへの対応

ネットワークの一時的な不安定さによる画像読み込みエラーは、リトライで解決できる場合があります。ただし、無制限のリトライはサーバーに負荷をかけるため、適切な制限と戦略が必要です。

指数バックオフによるリトライ:

function loadImageWithRetry(img, src, maxRetries = 3) {
let retries = 0;
img.onerror = () => {
if (retries < maxRetries) {
retries++;
const delay = Math.pow(2, retries) * 1000;
setTimeout(() => { img.src = src + '?retry=' + retries; }, delay);
} else {
img.src = '/images/fallback.svg';
img.onerror = null;
}
};
img.src = src;
}

リトライ間隔は 2 秒、4 秒、8 秒と指数的に増加させます。クエリパラメータ (?retry=N) を付与することで、CDN のキャッシュされたエラーレスポンスを回避します。

Intersection Observer との組み合わせ: 遅延読み込みと組み合わせる場合、ビューポートに入ったタイミングで読み込みを開始し、エラー時にリトライする構成が効果的です。ユーザーがスクロールして画像が見える位置に来た時点でリトライが実行されるため、不要なリクエストを最小限に抑えられます。

Service Worker によるオフラインフォールバック: Service Worker を使えば、オフライン時に自動的にキャッシュ済みのフォールバック画像を返すことができます。ネットワークリクエストが失敗した場合に、事前にキャッシュしておいたプレースホルダー画像を返す実装が可能です。

リトライすべきでないケース: 404 や 403 エラーはリトライしても解決しません。fetch API で事前にステータスコードを確認し、4xx エラーの場合は即座にフォールバックに切り替える判断が効率的です。リトライは 5xx エラーやネットワークエラーに限定してください。

監視とエラーレポーティング - 画像エラーの可視化と改善

画像エラーを検知し、継続的に改善するための監視体制を構築します。エラーの発生状況を可視化することで、問題の早期発見と対応が可能になります。

エラーイベントの収集:

window.addEventListener('error', (event) => {
if (event.target.tagName === 'IMG') {
const errorData = {
src: event.target.src,
alt: event.target.alt,
page: window.location.href,
timestamp: Date.now()
};
navigator.sendBeacon('/api/image-errors', JSON.stringify(errorData));
}
}, true);

navigator.sendBeacon を使用することで、ページ遷移時にもデータが確実に送信されます。addEventListener の第 3 引数に true を指定してキャプチャフェーズでイベントを捕捉する点が重要です。

監視すべきメトリクス:

アラート設定: 画像エラー率が通常の 2 倍を超えた場合にアラートを発報する設定を推奨します。CDN の障害やデプロイミスによる大量エラーを早期に検知できます。

定期的な死活監視: 重要な画像 (ロゴ、ヒーロー画像、主要商品画像) に対して、定期的に HTTP リクエストを送信し、200 レスポンスが返ることを確認する外形監視を実装してください。Uptime Robot や AWS CloudWatch Synthetics などのサービスが利用可能です。

関連記事

画像の遅延読み込み実装ガイド - loading=lazy と IntersectionObserver の使い分け

Web ページの初期表示速度を改善する画像遅延読み込みの実装方法を、ネイティブ API と JavaScript の両アプローチで解説します。

画像読み込み戦略の設計 - preload, fetchpriority, decoding を使いこなす

Web ページの画像読み込みを最適化する 3 つの属性を徹底解説。LCP 改善に直結する preload、fetchpriority、decoding の正しい使い方と組み合わせ方を紹介。

Data URI で画像を埋め込む技術と注意点 - Base64 エンコードの仕組みと最適な使いどころ

Data URI スキームで画像を HTML/CSS に直接埋め込む技術を解説。Base64 エンコードの仕組み、パフォーマンスへの影響、適切なユースケースと避けるべきケースを整理します。

画像プレースホルダー技術の比較 - LQIP, BlurHash, SQIP の実装ガイド

画像読み込み中のユーザー体験を向上させる LQIP、BlurHash、SQIP の仕組みと実装方法を比較解説。各手法のメリット・デメリットと最適な使い分けを紹介します。

Retina ディスプレイ対応画像の作り方 - 高 DPI 環境での鮮明な表示を実現する

Retina や高 DPI ディスプレイで画像がぼやける原因と対策を解説。srcset 属性、image-set()、SVG 活用、最適な書き出し設定まで実践的に紹介します。

HTML イメージマップの作り方と代替手段 - クリッカブルマップの実装ガイド

HTML の map 要素と area 要素を使ったイメージマップの実装方法を解説。レスポンシブ対応の課題と、SVG や CSS を使ったモダンな代替手段を具体的なコード例とともに紹介します。

関連用語