本文へスキップ

エラー状態

読み込み失敗をその場で伝えるエラーパネル。「再試行」を押すと一瞬スピナーが回り、成功状態へ切り替わる。

プレビュー

クリック

操作クリック/タップで動きます。

仕様書

向く場面
  • 通信失敗・API エラーの領域単位の差し替え
  • その場でやり直せる失敗
  • ダッシュボードの一部ウィジェットの失敗
避ける場面
  • ログイン切れなど遷移が要る失敗
  • 入力ミス(インライン検証で)
  • 成功後に自動リセットする本番実装
構成要素
  • パネル
  • 状態アイコン
  • メッセージ
  • 補足文
  • 再試行ボタン
  • スピナー
持っている状態
  • 通常
  • ホバー
  • フォーカス
  • 押下中
  • 無効
  • 読み込み中
  • エラー
  • 成功
キーボード

Tab で「再試行」ボタンに到達・Enter/Space で再試行。再試行中は disabled で押せない

支援技術

パネルは aria-live=polite で再試行中・成功の変化を穏やかに通知(初回のエラー表示だけ role=alert の要素に載せる)。アイコン svg は aria-hidden

動き

スピナー 0.7s linear 回転(1.3s の疑似通信)。成功時に背景 200〜300ms で緑へ。2.6s 後に自動で初期状態へ(デモ用)。reduced-motion では回転せず文言で示す

デザインの要点

  • 失敗した領域だけをこのパネルに差し替える。画面全体を置き換えると、どこが失敗したか分からない
  • 再試行中はボタンを disabled にして文言を「再試行中…」に変える。スピナーだけだと押せるのか分からない
  • 成功は背景を緑に、アイコンをチェックに差し替える。文言だけの変化は見落とされる
  • 変化の通知は aria-live=polite に留める。再試行中や成功まで assertive で割り込むと読み上げを毎回中断する

使いどころ

通信エラー・API失敗・タイムアウトなど、その場でやり直せる失敗を伝える場面に向く。画面全体を差し替えるのではなく、失敗した領域だけをこのパネルに置き換えることで、ユーザーはどこが失敗したのか正確に把握でき、再試行ボタンで同じ操作を繰り返せる。逆に、認証切れで別ページへの遷移が必要な場合や、入力バリデーションのようにユーザー側の入力ミスが原因の場合には向かない。前者はログインページへの誘導、後者はフォームのインライン検証メッセージの方が適切になる。1画面に複数のデータ取得が独立している場合(ウィジェットが並ぶダッシュボードなど)は、失敗した部分だけをこのパネルに差し替え、他のウィジェットは正常表示のまま残すのが基本方針になる。

仕組み

failure/loading/successの3状態をerr-btn要素へのクラス付け外し(is-loading・is-ok)で切り替える単純な状態機械になっている。クリックするとまずis-loadingを付けてボタンを無効化し、setTimeoutで通信を疑似的に1.3秒待った後、is-okへ切り替えてアイコン・メッセージ・サブテキストをすべてinnerHTMLで書き換える。成功表示は2.6秒後に自動でresetPanelへ戻るが、これはデモ用の挙動で、実際のアプリでは成功後はパネルごと本来のコンテンツへ置き換えるのが普通なので、自動リセットのタイマーはそのまま持ち込まないこと。スピナーはborder-top-colorだけ変えたCSSアニメーションで、DOM要素自体は最初から存在し、is-loadingクラスの有無で表示・非表示を切り替えている。

実装の注意

実装をコピーする際に見落としやすいのが、resetTimerがグローバル変数扱いで複数のエラーパネルを1ページに置くと状態が競合すること。パネルごとにタイマーとDOM参照をカプセル化する必要がある。また再試行中にボタンを無効化しているが、ネットワークが実際に不安定な状況では1.3秒のタイムアウトでは短すぎることがあり、本番実装ではfetchの実際の完了を待つPromiseベースの制御に置き換える必要がある。さらにこのデモは常に成功で終わる作りになっているため、実際には失敗が続くケースの表示(「何度も失敗する場合はサポートへ」のような案内や連絡先リンク)も併せて用意しておくと、ユーザーが手詰まりにならずに済む。

アクセシビリティ

パネル全体にはaria-live="polite"を付けてあり、再試行中・成功といった中身の変化は、いま読み上げている内容を中断せずに順番に伝えられる。以前はrole="alert"(assertive)を付けていたが、緊急度の低い変化にまで割り込むとユーザーの読み上げ操作を頻繁に中断してしまうため改めた。エラーが発生した瞬間だけは強く知らせたいので、実装するときは、初回のエラー表示を差し込む要素にrole="alert"を付けて挿入し、再試行中・成功などの穏やかな変化はこのpoliteなパネルに任せるなど、緊急度に応じてlive領域を使い分けるとよい。ボタンのラベル文言(再試行→再試行中…→読み込めました)はbutton内のテキストノードとして変わるため、フォーカスが当たったままの操作でも変化が読み上げに乗る。

調整して使う

調整しやすいのは3点。まず自動リセットの有無と間隔(既定2.6秒)で、実運用では自動で消さずユーザーの次の操作まで表示し続ける設計に変えることが多い。次にアイコンとメッセージの組み合わせで、通信エラー・権限エラー・サーバーエラーなど原因別にアイコン(三角の警告・鍵マーク・雲に斜線など)とメッセージを出し分けると、ユーザーが取るべき行動を判断しやすくなる。最後に再試行の上限で、このデモは何度でも再試行できるが、実際には3回失敗したら再試行ボタンをサポート連絡導線に差し替えるなど、失敗が続く場合のエスカレーションを用意すると親切になる。パネルの置き場所もページ全体を覆うか一部だけ差し替えるかで印象が変わる。

コード(コピーして使えます)

<div class="stage" id="stage">
  <div class="err" id="errPanel" aria-live="polite">
    <div class="err-icon" id="errIcon" aria-hidden="true">
      <svg class="err-ic-fail" id="errIcFail" width="26" height="26" viewBox="0 0 24 24" fill="none">
        <path d="M12 3L1.5 21h21L12 3Z" stroke="#c0492f" stroke-width="2" stroke-linejoin="round"/>
        <line x1="12" y1="10" x2="12" y2="14.5" stroke="#c0492f" stroke-width="2" stroke-linecap="round"/>
        <circle cx="12" cy="17.6" r="1.1" fill="#c0492f"/>
      </svg>
      <svg class="err-ic-ok" id="errIcOk" width="26" height="26" viewBox="0 0 24 24" fill="none" hidden>
        <circle cx="12" cy="12" r="10" stroke="#2a7a45" stroke-width="2"/>
        <path d="M7.5 12.5l3 3 6-6.5" stroke="#2a7a45" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
      </svg>
    </div>
    <p class="err-msg" id="errMsg">読み込みに失敗しました</p>
    <p class="err-sub" id="errSub">通信環境をご確認のうえ、もう一度お試しください。</p>
    <button class="err-btn" id="retryBtn" type="button">
      <span class="err-spinner" id="errSpinner" aria-hidden="true"></span>
      <span class="err-label" id="errLabel">再試行</span>
    </button>
  </div>
</div>

タグ

同じカテゴリ「エラー・システム状態」のほかのパーツ

関連パーツ