【jQuery】ローディング画面を実装する完全ガイド|スピナー・フェード・Ajax連動まで

Webページの読み込み中にローディング画面を表示することで、ユーザーが「止まっているのか?」と不安にならないようにできます。本記事ではページ読み込み中のオーバーレイ・スピナー・Ajax通信中の表示・フェードアウトまで解説します。

この記事でわかること

  • ページ読み込み中にローディング画面を表示する方法
  • CSSスピナーアニメーションの実装
  • Ajax通信前後にローディングを表示/非表示する方法
  • グローバルAjaxイベント(ajaxStart/ajaxStop)の活用
  • ローディング画面のフェードアウトと非表示のポイント
スポンサーリンク

1. ページ読み込み中のローディング画面

最もシンプルな実装です。HTMLに#loading要素を置き、ページ読み込み完了(window.load)時にフェードアウトします。

<!-- ローディングオーバーレイ(bodyの先頭に置く) -->
<div id="loading">
  <div class="spinner"></div>
</div>
#loading {
  position: fixed;
  top: 0; left: 0;
  width: 100%; height: 100%;
  background: rgba(255, 255, 255, 0.95);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;
}

/* CSSスピナー */
.spinner {
  width: 48px; height: 48px;
  border: 5px solid #e2e8f0;
  border-top-color: #0284c7;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}
@keyframes spin {
  to { transform: rotate(360deg); }
}
// window.load: 画像・CSSを含む全リソースの読み込み完了後に発火
$(window).on('load', function () {
  $('#loading').fadeOut(400);
});

// タイムアウト保険: 10秒後には必ず非表示(ネットワーク障害対策)
setTimeout(function () {
  $('#loading').fadeOut(400);
}, 10000);
$(document).ready() ではなく $(window).on(“load”) を使う
$(document).ready() はDOMが構築された時点で発火するため、画像やCSSの読み込みが完了していません。ローディング画面の非表示には $(window).on("load") を使ってページの全リソース読み込み完了を待ちます。

2. Ajax通信中にローディングを表示する

Ajax通信の前後にshow()/hide()でローディングを制御するパターンです。

function fetchData() {
  $('#loading').show();

  $.ajax({
    url: '/api/data',
    method: 'GET',
    success: function (data) {
      // データを表示する処理
      console.log(data);
    },
    error: function () {
      alert('データの取得に失敗しました');
    },
    complete: function () {
      $('#loading').hide();  // 成功・失敗にかかわらず必ず非表示
    }
  });
}

3. グローバルAjaxイベントで自動制御

ページ内の全Ajaxリクエストに対して自動でローディングを表示したい場合は、グローバルAjaxイベントを使います。

// 全Ajaxリクエスト開始時に自動表示
$(document).on('ajaxStart', function () {
  $('#loading').fadeIn(200);
});

// 全Ajaxリクエスト完了時に自動非表示
$(document).on('ajaxStop', function () {
  $('#loading').fadeOut(400);
});
ajaxStart/ajaxStopの注意点
ajaxStart はその時点でAjaxリクエストが1件もない状態から最初のリクエストが始まったときに発火します。ajaxStop は全てのAjaxリクエストが完了したときに発火します。複数リクエストが同時に走っていても1回だけ発火するため、カウンター管理が不要です。

4. ボタンクリック時のローディング表示

「送信中…」のインジケーターをボタン内に表示するパターンです。

<button id="submit-btn">送信する</button>
$('#submit-btn').on('click', function () {
  var $btn = $(this);
  var originalText = $btn.text();

  $btn.prop('disabled', true)
      .html('<span class="spinner-sm"></span> 送信中...');

  $.ajax({
    url: '/api/submit',
    method: 'POST',
    complete: function () {
      $btn.prop('disabled', false).text(originalText);
    }
  });
});

まとめ

場面 実装方法
ページ全体の読み込み中 $(window).on(“load”)でfadeOut()
特定のAjaxリクエスト中 beforeSend/completeでshow()/hide()
全Ajaxリクエストに対応 ajaxStart/ajaxStopイベント
ボタン送信中 disabled + テキスト変更

関連記事: jQueryのアニメーション完全ガイド(fadeIn/fadeOut) / jQueryでクリックを禁止・無効化する方法

よくある質問(FAQ)

Q$(window).on(“load”)と$(document).ready()の違いは?
A$(document).ready() はDOMのみの構築完了時に発火します(画像はまだ読み込み中の場合あり)。$(window).on("load") は画像・CSS・スクリプトを含む全リソースの読み込み完了後に発火します。ローディング画面の非表示には後者を使います。
Qローディング画面が消えない場合は?
A巨大な画像や重いリソースがあると window.load がなかなか発火しないことがあります。タイムアウト処理(setTimeoutで強制非表示)を実装して、いつまでも表示され続けることがないようにしてください。
QCSSスピナーはどのブラウザで使えますか?
Aanimationborder-radius を使うスピナーはIE10以上・全モダンブラウザで動作します。IE11対応が不要なら @keyframes ベースのアニメーションは問題なく使えます。
QSPA(シングルページアプリ)でルート遷移時にも表示するには?
ASPA(React/Vue/Angularなど)では独自のルーターイベントを使います。jQueryを使っている従来型のWebサイトでは、Ajaxでコンテンツを差し替える処理の前後でshow()/hide()を呼ぶのが基本です。
Qローディング中はスクロールを禁止するには?
A$("body").css("overflow", "hidden") でスクロールを禁止し、ローディング非表示時に $("body").css("overflow", "") で解除します。