ローディング画面を設定する

読み込み中は画面全体をローディング画面で覆い、読み込みが終わったらフェードアウトして消える土台。ローディングアニメーションは、土台の決まった箇所に追加するだけで使える。
アニメーションのみを紹介している記事あるので、それと組み合わせることでローディング画面となる。

ローディング画面の動き

状態ローディング画面
読み込み中画面全体を覆って、ローディングアニメーションを中央に表示する
読み込み完了フェードアウトして消える
読み込みが速い0.8秒は表示してから消す
10秒たっても読み込み中読み込み完了と同じく、フェードアウトして消える
JavaScript が動かない最初から表示しない

※ フェードアウトしたあとは、ローディング画面の HTML(#page-loader)をページから削除する。透明になったローディング画面がページの上に残らないようにするため。
※ 読み込みが速くても0.8秒は表示するのは、一瞬だけ表示されてチラつくのを防ぐため。
※ 10秒で消すのは、画像の多いページなどで、ローディング画面が消えなくなるのを防ぐため。

jQuery は不要。設定するのは <head> 内と <body> の直後の2か所。

CSS と noscript

<head> 内に配置。

<!-- ローディング画面(<head> 内に配置)
     JavaScript が動かない環境では、ローディング画面を表示しない(表示したまま消えなくなるのを防ぐ) -->
<noscript><style>#page-loader { display: none !important; }</style></noscript>
<style>
/* ===== ここから CSS(ローディング画面) ===== */

/* ローディング画面:画面いっぱいに重ねて、ローディングアニメーションを中央に表示する */
#page-loader {
  position: fixed;
  inset: 0;
  z-index: 99999;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #F2F2F2;                      /* ★ ローディング画面の色 */
  opacity: 1;
  transition: opacity .5s ease;             /* ★ 消える速さ */
}

/* 読み込みが終わったら、JavaScript が is-hide を追加してフェードアウトさせる */
#page-loader.is-hide {
  opacity: 0;
  pointer-events: none;
}

/* ===== ここまで CSS(ローディング画面) ===== */

/* ===== ローディングアニメーションの CSS は、ここから下に追加 ===== */
</style>

※ JavaScript が動かない環境では、<noscript> でローディング画面を表示しない。ローディング画面を消すのは JavaScript なので、表示したまま消えなくなるため。

HTML と JavaScript

<body> の直後に配置。

<!-- ローディング画面(<body> の直後に配置) -->
<div id="page-loader" role="status" aria-label="読み込み中">

    <!-- ▼ ここにローディングアニメーションの HTML を追加
    (CSS は <head> 内のコードの「CSS は、ここから下に追加」の下、JavaScript はこのコードの一番下に追加) -->
    <!-- ▲ ここまで -->

</div>

<script>
/* ===== JavaScript(ローディング画面) =====
   ・ページの読み込みが終わったら(load)、ローディング画面をフェードアウトして削除する
   ・読み込みが速くても、MIN_SHOW のあいだは表示する(一瞬だけ表示されてチラつくのを防ぐ)
   ・読み込みが終わらなくても、MAX_WAIT を過ぎたら消す(表示したまま消えなくなるのを防ぐ)
   ・ローディング画面の HTML より後ろに配置する(HTML より前だと #page-loader が見つからないため) */
(function () {
  var MIN_SHOW = 800;     /* ★ 最低の表示時間(ミリ秒) */
  var MAX_WAIT = 10000;   /* ★ 最大の待ち時間(ミリ秒) */

  var loader = document.getElementById('page-loader');
  if (!loader) { return; }

  var startedAt = Date.now();
  var done = false;

  /* ローディング画面を削除する */
  function remove() {
    if (loader.parentNode) { loader.parentNode.removeChild(loader); }
  }

  /* ローディング画面を消す(1回だけ) */
  function hide() {
    if (done) { return; }
    done = true;
    var wait = Math.max(0, MIN_SHOW - (Date.now() - startedAt));   /* MIN_SHOW に足りない分だけ待つ */
    setTimeout(function () {
      loader.classList.add('is-hide');                                       /* フェードアウト開始 */
      var d = parseFloat(getComputedStyle(loader).transitionDuration) || 0;  /* CSS の transition の時間(秒) */
      if (d === 0) { remove(); return; }                                     /* フェードなし:すぐ削除 */
      loader.addEventListener('transitionend', function (e) {                /* フェードあり:終わったら削除 */
        if (e.target === loader) { remove(); }                               /* ローディングアニメーションの transition の終わりでは削除しない */
      });
      setTimeout(remove, d * 1000 + 200);                                    /* transitionend が来なかったときの予備 */
    }, wait);
  }

  /* 読み込み完了で消す(すでに終わっていればすぐ) */
  if (document.readyState === 'complete') {
    hide();
  } else {
    window.addEventListener('load', hide);
  }
  setTimeout(hide, MAX_WAIT);
})();
</script>

<!-- ===== ローディングアニメーションの JavaScript は、ここから下に追加 ===== -->

※ JavaScript は、ローディング画面の HTML より後ろに配置する。HTML より前に配置すると、JavaScript が #page-loader を見つけられないため。
※ 読み込み完了は load で判断している。画像なども含めて、ページの読み込みが全部終わったときに起きるため。
※ フェードアウトの終わりは、ローディング画面自体の transition だけで判断している。ローディングアニメーションが transition を使っていても、フェードアウトの途中で削除されないようにするため。

ローディングアニメーションを追加する

追加するのは、ローディングアニメーションの HTML・CSS・JavaScript の3つ(JavaScript がないものは2つ)。

追加箇所

  • HTML:<body> の直後のコードの「▼ ここにローディングアニメーションの HTML を追加」〜「▲ ここまで」の間
  • CSS:<head> 内のコードの「ローディングアニメーションの CSS は、ここから下に追加」の下
  • JavaScript:<body> の直後のコードの「ローディングアニメーションの JavaScript は、ここから下に追加」の下

たとえば CSSだけでローディングアニメーションを作る#01 の円の場合は、HTML の間に <div class="loader"></div> を、CSS の下に「CSS(ローディングアニメーション:円)」を追加する。

JavaScript を使うローディングアニメーションの場合

JavaScript で動かし続けるローディングアニメーションは、ローディング画面ごと削除されたら止める処理が必要。止めないと、画面から消えたあとも裏で動き続けるため。

CSSとJavaScriptでローディングアニメーションを作る#01・#02 は、止める処理を入れてある。ほかのローディングアニメーションを追加する場合は、動かし続ける処理の先頭で、要素が画面に残っているかを確認する。

if (!el.isConnected) { return; }   /* el はローディングアニメーションの要素。ローディング画面ごと削除されたら止める */

変更する場合

変えたいもの変更箇所
ローディング画面の色CSS の #page-loader の background
消える速さCSS の #page-loader の transition
最低の表示時間JavaScript の MIN_SHOW
最大の待ち時間JavaScript の MAX_WAIT

※ transition を削除すると、フェードアウトせずにすぐ消える。

WordPress で設定する場合

functions.php に追記。<head> 内のコードを wp_head、<body> の直後のコードを wp_body_open で出力する。

/**
 * ローディング画面
 * ・wp_head      :<head> 内のコード(CSS と noscript)を出力
 * ・wp_body_open :<body> の直後のコード(HTML と JavaScript)を出力
 */
function page_loader_head() {
	?>
	<!-- 「CSS と noscript」のコードを、この行と入れ替えて追記 -->
	<?php
}
add_action( 'wp_head', 'page_loader_head' );

function page_loader_body() {
	?>
	<!-- 「HTML と JavaScript」のコードを、この行と入れ替えて追記 -->
	<?php
}
add_action( 'wp_body_open', 'page_loader_body' );

※ コメントの行(<!-- … -->)を、「CSS と noscript」「HTML と JavaScript」のコードと1つずつ入れ替える。
※ wp_body_open は、テーマの header.php の <body> の直後に <?php wp_body_open(); ?> があるときに動く。ない場合は、header.php の <body> の直後に <?php wp_body_open(); ?> を追記する。

既存の設定がある場合

ページ全体を隠して表示する設定(body { display: none; } からのフェードインなど)や、別のローディング画面がすでにある場合は、先に削除してから設定する。

たとえば jQuery のフェードインの場合に削除するもの

  • body { display: none; } の <style>
  • $('body').fadeIn(2000); の <script>

※ ページを隠す設定が残ったままだと、ローディング画面もページごと隠れた状態から始まり、ローディングアニメーションが最初から見えなくなる。

表示環境によって動きの見え方が異なる場合があるため、本番に反映する前に確認してね。

NOTICES

  • 記事内容は実装させたものがほとんどですが自己責任で参考にしてください。