【CSS講座第7回】ローディング画面の作り方

サイトにアクセスするとローディング画面が表示されることが多くなってきました。

ゲームとかによくありがちなローディング画面ですが、 Webだと本来は必要ないんですが何も表示されていないと不安になる人も結構いるのと、 スペックの低い端末や回線速度の遅い人にきれいに見せるためのものですね。

正直ローディング画面なんて挟まずにすぐに表示するぐらい、 高速で軽量なWebページ作りを心がけるべきなのですが、 どうしてもグラフィカルなWebページにしたいときはローディング画面を実装せざるを得ない時が来ます。

結論だけ先に説明しておくと、ローディング画面はCSSで基本的な見た目を作り JavaScriptでロードが完了したかどうかを監視しつつローディング画面の制御を行います。

今回はCSS講座になりますので見た目の作り方に焦点を当てていきます。

そのうちjQueryを使わないJavaScript講座でもやろうと思ってるので、 それとセットで見てもらったらいいかもって感じの作りにします。

<body> <div class="loading--wrap"></div> <div class="all--wrap"> <h1>コンテンツタイトル</h1> <p>コンテンツ内容</p> </div> </body>

イメージ的にはコンテンツの上に覆いかぶさるような感じです。

HTMLに関してはこれで終わりです。

.loading--wrap { width:100%; height:100%; position:fixed; z-index:9999; background-color:#ccf; }

これでall--wrapクラスの上に薄い青の背景が覆いかぶさって 画面全体が塗りつぶされた状態になります。

ローディング画面の土台はこれで完了です。

背景色はお好きに変更してください。

.loading--wrap { width:100%; height:100%; position:fixed; z-index:9998; background-color:#ccf; } .loading--wrap::after { content:''; border:5px solid #ff0000ff; border-right-color: #ff000055; border-top-color: #ff000055; border-radius:50%; width:70px; height:70px; position:absolute; z-index:9999; left:50%; top:50%; transform:translate(-50%,-50%); }

これで中央に赤いサークルが出来ました。

ボーダーの右と上のカラーは元のカラーより透過度を上げたものにしています。

透過度を設定するには本来カラーを設定する16進法6桁+2桁にしてやれば設定できます。

別のやり方として「rgba(255,255,255,0.5)」という書き方もできます。

RGBA指定の場合はカラーが0~255で透過度は0.0~1.0の範囲になるのに注意してください。

何故かCodepenだとrgba法が動かなかったので今回は16進法の8桁にしています。

指定方法はお好みでどうぞ。

後はこれをぐるぐる回せばローディングアイコンとして成り立ちます。

続けてこのアイコンを回すためにCSSアニメーションを実装していきましょう。

.loading--wrap {
  width:100%;
  height:100%;
  position:fixed;
  z-index:9998;
  background-color:#ccf;
}

.loading--wrap::after {
  content:'';
  border:5px solid #ff0000ff;
  border-right-color: #ff000055;
  border-top-color: #ff000055;
  border-radius:50%;
  width:70px;
  height:70px;
  position:absolute;
  z-index:9999;
  left:50%;
  top:50%;
  transform:translate(-50%,-50%);
  animation: loader 0.5s linear infinite;
}

@keyframes loader {
  0% {
    transform: rotate(0);
  }

  100% {
    transform: rotate(360deg);
  }
}

追加したのはanimationプロパティと「@keyframes」の部分です。

今回はアニメーションについては解説しませんが、 手順としてはkeyframeで状態をキーフレームごとに設定できるようになっています。

パラパラ漫画みたいな感じで0%~100%までのアニメーションの始まりから終わりまで自由に指定できます。

複雑なアニメーションを作る場合は手動では正直時間の無駄なので AdobeのAfterEffectsやAnimateなんかでアニメーションを作って CSSとして出力すれば簡単に複雑なCSSアニメーションを作ることが出来ます。

今回はローディングアイコンをぐるぐる無限に回すだけなので、 最初と最後だけ状態を設定すれば後はCSS側で0度から360度までの間を いい感じに補完してくれるので楽ですね。

次に「animation」プロパティで先程作ったkyeframeの名前を設定して どんな感じの遷移アニメーションにするか、終わりはどうするのかを設定します。

今回は特に緩急をつける必要のないアニメーションなので、 動きは終始一定の速度となる「linear」に設定しました。

次にアニメーションの終わりをどうするかの設定ですが、 ずっとぐるぐる回したいので無限に再生する「infinite」を指定しました。

これでアイコンがぐるぐる回るようになるので、 薄い色を指定した部分のおかげで回転しているのが視覚的にわかるようになっています。

すべて同じ色だと回っているのが分かりづらいためですね。

ローディングアイコンは今回はシンプルなサークルにしましたが、 様々な形をつくることが出来るので好きなローディング画面の実装にチャレンジしてみてください。

.loading--wrap { width:100%; height:100%; position:fixed; z-index:9998; background-color:#ccf; opacity:1; transition:opacity 1s linear; } .loaded { opacity:0 !important; }

次にロードが終わったらopacity:0のクラスを取り付けます。

// loadingオブジェクトを取得
var loading = document.getElementsByClassName("loading--wrap")[0];

// ロードが終わったら動かす処理を実装
window.addEventListener('load', function() {
  loading.classList.add('loaded');
});

これでロードが終わったら自動的にloadedクラスが付与されて opacityが徐々に0になっていきます。

しかし、このままだと透明になっただけで上にかぶさっているため 内部のコンテンツをクリックしたりできなくなってしまいます。

なのでopacityが0になったらローディング用のタグを非表示にしてやる必要があります。

非表示といえば「display:none」が有名ですが、これだと存在そのものが消えてしまい フェードアニメーションが適用されなくなったりしてしまうため 基本的にアニメーションして消したいようなものは「visibility:hidden」を使用します。

今回の場合は別にdisplay:noneで消し去っても大丈夫なのでお好みで選択してください。

そしてCSSだけではopacityが0になった時にJavaScriptを動かしたいので、 以下のようなイベントリスナーを設定します。

// loadingオブジェクトを取得
var loading = document.getElementsByClassName("loading--wrap")[0];

// ロードが終わったら動かす処理を実装
window.addEventListener('load', function() {
  loading.classList.add('loaded');
});

// loadingのtransitionが動作完了後に動かすイベントリスナー
loading.addEventListener('transitionend', function() {
  loading.style.visibility = "hidden";
});

「loadingのtransitionが動作完了後に動かすイベントリスナー」で設定した項目は 視覚的にはちょっと分かりづらいですが、ない時とある時を試してもらって 中身のコンテンツをドラッグして選択状態にできるかを試してもらうとよくわかります。

これを指定してないと上に透明の画面全体のブロックが重なっているため、 うまく中身のコンテンツを触ることが出来ない状態になりますので、 フェードアウトしたらブロックを非表示にするの忘れないようにしましょう。

中身がそれほど重くないとローディング画面がすぐに終わってしまうので 最低2~3秒ローディング画面を見せるというやり方を併用したほうがいいかも知れません。

その場合はJavaScriptでタイマーを作らないといけない上に 非同期処理をして上げる必要があるので初心者からするとちょっと難易度は高いかなと思います。

最後に今回のコードをまとめておきます。

CodePenなんかにコピペしてもらうと動作がわかりやすいかなと思います。

それでは。

HTML

<div class="loading--wrap"></div>
<div class="all--wrap">
  <h1>コンテンツタイトル</h1>
  <p>コンテンツ内容</p>
</div>

CSS

.loading--wrap {
  width:100%;
  height:100%;
  position:fixed;
  z-index:9998;
  background-color:#ccf;
  opacity:1;
  transition:opacity 1s linear;
}

.loaded {
  opacity:0 !important;
}

.loading--wrap::after {
  content:'';
  border:5px solid #ff0000ff;
  border-right-color: #ff000055;
  border-top-color: #ff000055;
  border-radius:50%;
  width:70px;
  height:70px;
  position:absolute;
  z-index:9999;
  left:50%;
  top:50%;
  transform:translate(-50%,-50%);
  animation: loader 0.5s linear infinite;
}

@keyframes loader {
  0% {
    transform: rotate(0);
  }

  100% {
    transform: rotate(360deg);
  }
}

JavaScript

// loadingオブジェクトを取得
var loading = document.getElementsByClassName("loading--wrap")[0];

// ロードが終わったら動かす処理を実装
window.addEventListener('load', function() {
  loading.classList.add('loaded');
});

// loadingのtransitionが動作完了後に動かすイベントリスナー
loading.addEventListener('transitionend', function() {
  loading.style.visibility = "hidden";
});