Back

Webアプリにおけるローディングインジケーターのクイックガイド

Webアプリにおけるローディングインジケーターのクイックガイド

ユーザーがボタンをクリックしました。何かが起こっている—しかし何が?明確なフィードバックがなければ、ユーザーは最悪の事態を想定します。アプリが壊れている、操作が失敗した、もう一度クリックする必要がある、と。ローディングインジケーターはこの問題を解決しますが、誤ったアプローチは新たな問題を生み出します。

本ガイドでは、適切なパターンの選択からReact Suspenseのローディング状態の実装、Next.js App Routerのloading.tsx規約まで、INP Core Web Vitalsを健全に保ちながら、最新のローディングインジケーターUXについて解説します。

重要なポイント

  • グローバルスピナーはインタラクションをブロックし、ユーザーエクスペリエンスとINPスコアの両方を損ないます—代わりにローカライズされた段階的なフィードバックを使用してください。
  • 状況に応じてインジケーターを選択しましょう:短時間の待機にはスピナー、コンテンツの読み込みにはスケルトン、測定可能な操作にはプログレスバー、瞬時に感じられるアクションにはオプティミスティックUIを使用します。
  • React SuspenseバウンダリとNext.jsのloading.tsxは、セグメントスコープのローディング状態を可能にし、ユーザーがアプリの影響を受けない部分と対話できるようにします。
  • アクセシビリティは必須です:aria-busy、ライブリージョンを使用し、モーション低減設定を尊重してください。

グローバルスピナーが通常間違っている理由

フルページスピナーはすべてをブロックします。ユーザーはコンテンツを読むことも、他の場所に移動することも、生産的なことを何もできません。さらに悪いことに、実際の読み込み時間が妥当であっても、体感パフォーマンスを損ないます。

最新のアプローチ:ローカライズされた段階的なフィードバック。コンテンツが実際に読み込まれている場所でのみローディング状態を表示します。それ以外のすべてでユーザーが操作できるようにします。

これは、レスポンシブネスを測定するCore Web VitalであるINP(Interaction to Next Paint)にとって重要です。インタラクションをブロックするグローバルローディングオーバーレイは、INPスコアに悪影響を与える可能性があります。ローカライズされたインジケーターは、UIの残りの部分をレスポンシブに保ちます。

適切なインジケーターの選択

状況によって異なるパターンが必要です:

スピナー

3秒未満の短時間で不確定な待機に最適です。インライン(ボタン内、フォームフィールドの横、または小さなコンテンツエリア内)で使用してください。空の画面の中央にスピナーを配置することは避けてください。

スケルトンスクリーン

初期ページ読み込みやコンテンツセクションに理想的です。スケルトンは受信コンテンツの形状を表示し、体感待ち時間を短縮し、レイアウトシフトを防ぎます。リスト、カード、テキストが多いエリアで特に効果的です。

プログレスバー

確定的なプロセス(ファイルアップロード、複数ステップの操作、または実際の進捗を計算できるもの)のために予約してください。現実を反映しない偽のプログレスバーは、正直なスピナーよりもユーザーをイライラさせます。

オプティミスティックUI

保存、いいね、トグルなどのアクションについては、UIを即座に更新し、後でサーバーと調整します。ユーザーは瞬時のレスポンシブネスを感じます。ロールバックと明確なエラー状態で失敗を適切に処理してください。

機能するフレームワークパターン

React Suspenseのローディング状態

ReactのSuspenseバウンダリを使用すると、ローディングUIを宣言的に定義できます。非同期コンポーネントをフォールバック付きの<Suspense>でラップすれば、Reactが残りを処理します。React 19は、非同期トランジションと保留中のUI状態をファーストクラスにすることで、これをさらに改善し、状態間を移動する際の視覚的なジャンクを減らします。

重要な洞察:Suspenseバウンダリを戦略的にネストすることです。単一のトップレベルバウンダリは、まさに避けたいグローバルスピナーを提供します。複数の細かいバウンダリにより、異なるセクションが独立して読み込まれます。

Next.js App Routerのloading.tsx

App Routerのloading.tsx規約は、ルートセグメントごとに自動的にローディングUIを提供します。任意のルートフォルダにloading.tsxファイルを配置すると、Next.jsはそのセグメントの読み込み中にそれを表示します。

重要な詳細:これはセグメントスコープであり、ユニバーサルなグローバルローダーではありません。各ルートセグメントは独自のローディング状態を持つことができます。/dashboardloading.tsxは、アプリシェル全体ではなく、ダッシュボードセグメントにのみ影響します。

これは、ストリーミングSSRと自然に組み合わさります—コンテンツはデータが利用可能になるにつれて段階的にレンダリングされ、loading.tsxがギャップを埋めます。

View Transitions API

ページとルートの変更については、View Transitions APIが従来のローディングスピナーに代わる実行可能な選択肢になりつつあります。次のページが準備される間にローダーを表示する代わりに、ブラウザは状態間をスムーズにアニメーション化できます。実際の読み込み時間が同じでも、これはより速く感じられます。

このAPIはフレームワーク間で機能し、トランジションアニメーションをカスタマイズするためのCSSフックを提供します。両方のページを制御できる同一オリジンナビゲーションで特に効果的です。

アクセシビリティ要件

ローディングインジケーターはすべての人に機能する必要があります:

  • aria-busy="true":コンテンツが読み込まれているコンテナに適用します。スクリーンリーダーがビジー状態をアナウンスします。
  • ライブリージョン付きのrole="status":アナウンスすべきローディングメッセージに使用します。ユーザーを中断しないようにaria-live="polite"を使用してください。
  • モーション低減:prefers-reduced-motionを尊重してください。回転アニメーションを静的なインジケーターまたは微妙な不透明度の変化に置き換えます。
  • 視覚のみに依存しない:アニメーション化されたインジケーターをテキストラベルまたはARIAアナウンスと組み合わせます。「ダッシュボードを読み込んでいます…」は無音のスピナーより優れています。

よくある間違い

高速操作にローダーを表示する:何かが100ms未満で完了する場合、ローディングインジケーターはちらつきを生み出します。ローディング状態をデバウンスしてください—短い遅延の後にのみ表示します。

不必要にインタラクティビティをブロックする:アクションが本当に待機を必要とする場合(支払い確認など)を除き、ユーザーがアプリを使い続けられるようにします。

誤解を招くプログレスバー:2分間99%で停止しているプログレスバーは信頼を破壊します。実際の進捗を測定できない場合は、不確定なインジケーターを使用してください。

すでに読み込まれたコンテンツを隠す:データを更新する際は、すべてをスケルトンに置き換えるのではなく、微妙な更新インジケーター付きで古いコンテンツを表示してください。

結論

優れたローディングインジケーターUXは、正直さと局所性に帰着します。何が起こっているのか、どこで起こっているのかをユーザーに伝え、それ以外のすべてを実行できるようにします。React Suspenseのローディング状態、Next.js App Routerのloading.tsx、View Transitions APIなどの最新パターンは、INP Core Web Vitalsをチェックしながら、これをこれまで以上に簡単にします。

現在のローディング状態を監査することから始めてください。グローバルブロッカーをローカライズされたフィードバックに置き換えてください。ユーザー、そしてパフォーマンスメトリクスが感謝するでしょう。

よくある質問

リスト、カード、テキストブロックなど、予測可能なレイアウトを持つコンテンツを読み込む際にスケルトンスクリーンを使用してください。スケルトンは受信コンテンツの形状を表示することで、体感待ち時間を短縮します。スピナーは、短時間で予測不可能な待機や、ボタンやフォームフィールド内のインラインフィードバックに適しています。

ローディングインジケーターを表示する前に、通常100〜200ミリ秒の短い遅延を追加してください。遅延が期限切れになる前に操作が完了した場合は、インジケーターを完全にスキップします。これにより、本当に遅い操作に対してフィードバックを提供しながら、不快なちらつきを防ぎます。

いいえ。loading.tsxファイルはセグメントスコープです。つまり、配置されたルートセグメントにのみ影響します。dashboardフォルダのloading.tsxは、そのセグメントの読み込み中にのみ表示されます。アプリシェルの残りの部分はインタラクティブで影響を受けません。

読み込み中のコンテンツを持つコンテナにaria-busy trueを適用してください。アナウンスすべきローディングメッセージにはaria-live polite付きのrole statusを使用してください。アニメーションを見ることができないユーザーもフィードバックを受け取れるように、視覚的なインジケーターを常にテキストラベルまたはARIAアナウンスと組み合わせてください。

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay