JavaScript

レシピ

イベント

スクロールしたときに処理を実行する

ページがスクロールされたときに指定した処理を実行する方法を解説します。

この記事のポイント

  • ページをスクロールするとイベントscrollが発生する
  • スクロール量を参照するとページをどこまで表示したかチェックできる

目次

ページをスクロールするとイベントが発生する

ページをスクロールするとイベントscrollが発生します。
このイベントは縦スクロール、横スクロールのいずれも発生します。

スクロールした量はwindowオブジェクトscrollXプロパティ、またはscrollYプロパティから取得することができます。

横スクロールした量を出力
縦スクロールした量を出力

イベントscrollはスクロール中に何度も呼び出されるため、上記のプロパティの値を確認することでどこまでページをスクロールされたか確認することが可能です。

コード例

<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>GRAYCODE JavaScript</title>
	<script>
		window.addEventListener('DOMContentLoaded', function(){

			window.addEventListener('scroll', function(){
				console.log("横スクロール:" + window.scrollX);
				console.log("縦スクロール:" + window.scrollY);
			});

		});
	</script>
</head>
<body>
<h1>JavaScriptレシピ</h1>
<section id="content1"></section>
</body>
</html>

スクロールに応じてボタンの表示を切り替える

ページのスクロール量を確認することで、次のようにボタンの表示/非表示を切り替えることが可能です。
次の例はページを縦に200px以上スクロールしたら、「ページ先頭に戻る」ボタンを表示します。

ページを縦にスクロールすると...
ボタンを表示

コードは上記のものをベースに、赤字の箇所を変更しています。

コード例

<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>GRAYCODE JavaScript</title>
	<script>
		window.addEventListener('DOMContentLoaded', function(){

			document.getElementById('link_page_top').style.visibility = 'hidden';

			document.getElementById('link_page_top').addEventListener('transitionend', function(){

				if( document.getElementById('link_page_top').className !== 'view' ) {
					document.getElementById('link_page_top').style.visibility = 'hidden';
				}
			});

			window.addEventListener('scroll', function(){
				if( 200 < window.scrollY ) {
					document.getElementById('link_page_top').style.visibility = 'visible';
					document.getElementById('link_page_top').classList.add('view');

				} else {
					document.getElementById('link_page_top').classList.remove('view');
				}
			});
		});
	</script>
	<style>
		body {
			height: 2000px;
			background-color: #f7f7f7;
		}

		#content1 {
			padding: 20px;
			height: 300px;
			background-color: #3f98d1;
		}

		#link_page_top {
			position: fixed;
			right: 30px;
			bottom: 30px;
			padding: 10px;
			color: #fff;
			font-size: 86%;
			text-decoration: none;
			border-radius: 5px;
			background: #333;
			opacity: 0.0;
			transition: ease .3s opacity;
		}
		#link_page_top.view {
			opacity: 1.0;
		}
	</style>
</head>
<body>
<h1>JavaScriptレシピ</h1>
<section id="content1"></section>
<a id="link_page_top" href="#">ページ先頭に戻る</a>
</body>
</html>

CSS含めてたくさん追記していますが、実際に表示/非表示を行うボタンはコードの下部にある「<a id=”link_page_top” href=”#”>ページ先頭に戻る</a>」になります。

CSSの解説

まず、CSSの解説から入ります。

CSSは表示位置や見た目の調整も含むため一見多く見えますが、重要なのは不透明度を指定するopacityと、アニメーションを設定するtransition、そしてクラス.viewの箇所になります。

通常は「opacity: 0.0」でボタンの不透明度を0%に指定して非表示とし、クラス.viewのCSSが適用されると「opacity: 1.0」で不透明度が100%になり表示されるようになります。

このopacityプロパティ0%100%の切り替えをアニメーションにして表示するのがtransitionプロパティです。
このプロパティでは3つの値を指定していますが、前から順にアニメーションのエフィクト、アニメーションを実行する時間、アニメーションするプロパティになります。
3つ目に先ほどの「opacity」を指定することで、opacityプロパティをアニメーション表示することができるようになります。

JSの解説

続いて、JavaScriptコードの解説に入ります。
イベントリスナーDOMContentLoadedの内側のコードを上から順に解説していきます。

コード例

document.getElementById('link_page_top').style.visibility = 'hidden';

この1行目はページ読み込み時に1度だけ実行され、id属性link_page_top」を持つHTML要素(ページ先頭に戻るボタン)のvisibilityプロパティhiddenに設定します。
CSSのtransitionプロパティでopacityプロパティのアニメーションを滑らかに表示するためにJSでCSSを設定しています。

コード例

document.getElementById('link_page_top').addEventListener('transitionend', function(){

  if( document.getElementById('link_page_top').className !== 'view' ) {
    document.getElementById('link_page_top').style.visibility = 'hidden';
  }
});

次に、イベントリスナーでイベントtransitionendが発生したら、クラスviewの有無を調べて、ない場合は1行目と同様にvisibilityプロパティhiddenで非表示にしています。
このイベントtransitionendはCSSのtransitionプロパティによるアニメーションが終了したタイミングで発生し、上記のCSSでは「transition: ease .3s opacity;」のアニメーションが該当します。

アニメーションが終わったタイミングでCSSを変更するようにすることで、アニメーションの途中で急にボタンが非表示になってしまうようなぎこちなさを解消します。

コード例

window.addEventListener('scroll', function(){
  if( 200 < window.scrollY ) {
    document.getElementById('link_page_top').style.visibility = 'visible';
    document.getElementById('link_page_top').classList.add('view');

  } else {
    document.getElementById('link_page_top').classList.remove('view');
  }
});

最後のイベントリスナーでイベントscrollを登録する箇所では、if文の条件式でscrollYプロパティを参照し、ページが200px以上スクロールされているかをチェックします。
これでページが読み込まれたタイミングではスクロールが0なのでボタンは非表示になり、200px以上スクロールされたらボタンを表示する仕組みを実装することができます。
ちなみに、ページを上にスクロールして200pxより上に戻ると、ボタンは再び非表示になります。

200px以上スクロールされているときは、まずvisibilityプロパティを変更してボタンを表示した上で、クラスviewを追加します。
このクラスを追加したタイミングでtransitionプロパティによるアニメーションが開始され、ボタンがゆっくりフェードインするエフィクトをかけ流ことができます。

続いてelse文ですが、こちらはスクロール量が200px未満のときに発生します。
ここでは先ほどと反対にクラスviewを削除します。
クラスを削除した際にもopacityプロパティの値は変化するため、表示したときと同様にtransitionプロパティによるアニメーションが実行されます。

以上、ページのスクロール量に応じてボタンの表示/非表示を切り替える仕組みでした。

こちらの記事は役に立ちましたか?

ありがとうございます。
もしよろしければ、あわせてフィードバックや要望などをご入力ください。

コメントありがとうございます!
運営の参考にさせていただきます。