JavaScriptでスクロール時に要素が可視範囲に入ったらコンテンツを表示させる



Webページのスクロール時に、可視範囲に入ったコンテンツにアニメーションで動きを加えることで、ユーザーの目を引くことができます。特に重要なコンテンツにインパクトを与えるにはとても効果的です。

現在のスクロール位置の把握やフェード効果の処理を、JavaScriptでプログラムを構築しておけば、あとは対象のHTML要素にクラスを付与するだけで実装することができます。

ここでは純粋なJavaScriptで、スクロール時に要素が可視範囲に入ったらコンテンツを表示させる方法についてご紹介します。

スクロール時の表示のコントロール


ここからはサンプルコードを交えてご紹介していきます。

まずはHTML。
ファーストビューを含め、いくつかのセクションのコンテンツを構築してみました。

HTML

<section id="mv">
  <h1>JavaScript<br>Element Fadein on Scroll</h1>
</section>

<section>
  <div class="section-conts ef">
    <h2>HEADLINE</h2>
    <p>Example text... Example text... Example text... Example text... Example text... Example text... Example text... Example text... Example text... </p>
  </div>
</section>

<section>
  <div class="section-conts ef">
    <h2>HEADLINE</h2>
    <p>Example text... Example text... Example text... Example text... Example text... Example text... Example text... Example text... Example text... </p>
  </div>
</section>

<section>
  <div class="section-conts ef">
    <h2>HEADLINE</h2>
    <p>Example text... Example text... Example text... Example text... Example text... Example text... Example text... Example text... Example text... </p>
  </div>
</section>



スクロール時に可視範囲に入ったら表示させる要素には、CSSクラス「ef」を付与しておきます。
サンプルでは、セクションのコンテンツ全体に対して指定しています。

続いてはCSS。
ページ全体は、簡単なレイアウト調整をしておきます。

CSS

section {
  width: 100%;
  height: 100vh;
  background: #e7e7e7;
  padding: 3.75rem 0.625rem;
}

section:nth-child(even) {
  background: #d3d3d3;
}

.section-conts {
  max-width: 1000px;
  margin: auto;
}

#mv {
  display: flex;
  justify-content: center;
  align-items: center;
}

#mv h1 {
  font-size: 3rem;
  text-align: center;
  line-height: 1.8;
}

.section-conts h2 {
  margin: 0 0 1.25rem;
  text-align: center;
}

.ef {
  transition: opacity 1s;
}



CSSクラス「ef」が付与された要素には、transitionプロパティでopacityの変化を1秒かけてフェード効果が加わるようにします。
CSSの準備はこの3行だけになります。

ここからはJavaScriptを使って、CSSクラス「ef」が付与されているコンテンツに対して表示のコントロールをしていきます。
以下、JavaScriptのコードになります。

JavaScript

const scrollFade = () => {

  const fadeElem = document.querySelectorAll(".ef");
  const elemLength = fadeElem.length;
  for (i = 0; i < elemLength; i++) {
    fadeElem[i].style.opacity = 0;
  }

  window.addEventListener("scroll", (event) => {
    fadeElem.forEach((fadeElem) => {
      const ePos = fadeElem.offsetTop;
      const scroll = window.scrollY;
      const windowHeight = window.innerHeight;
      if (scroll > ePos - windowHeight + windowHeight/5){
        fadeElem.style.opacity = 1;
      }
    });
  });

}
scrollFade();



JavaScriptでは、スクロール時にフェード処理をする関数を作成します。
関数名は「scrollFade」としておきます。

まずはじめに、CSSクラス「ef」が付与されている要素を変数「fadeElem」に格納します。
querySelectorAll()メソッドで、複数の要素をNodeListオブジェクトとします。
変数「elemLength」には、複数ある要素の数を格納して、for文で対象の要素の数だけ、各要素を「style.opacity」でopacityの値を0として非表示にしておきます。

次に、「window.addEventListener(“scroll”, (event) => {}」でスクロール時の処理を記述します。
forEach()メソッドを使って、複数あるクラスに対して繰り返し処理を行います。
変数「ePos」では、スクロールした際に可視範囲に入ったクラス要素に対して、offsetTopプロパティで要素のTOPの位置を取得します。
変数「scroll」では、Webブラウザのウィンドウの最上部から、現在の垂直方向のスクロール位置をscrollYプロパティで取得します。
変数「windowHeight」では、innerHeightプロパティでウィンドウの高さを取得します。

ここからif文を用いて、3つの変数に入っている値を計算して対象の要素の位置を把握して処理を行います。
計算の中で、「windowHeight/5」を最後に足すことで、要素の可視範囲からウィンドウの高さの5分の1の高さ分スクロールしたら表示するようにしています。

if文の処理では、対象の要素に対してstyle.opacityプロパティで、非表示にした要素をopacityの値を1として表示させます。このとき、CSSクラス「ef」にスタイルシートで適用させているtransitionプロパティの値によって、opacityプロパティで透過度を1秒間で変化させてフェード効果が実装されます。

以下、実際の実行結果になります。
動画(2分30秒)



JavaScriptのプログラムを作っておけば、あとは対象の要素に対して「ef」というクラスを付与するだけとなります。
サンプルでは、セクションごとにフェード効果を加えて表示させていますが、要素ごとに必要な部分だけアニメーションを加えるのもいいでしょう。