スクロールアニメーションを取り入れているサイト誰でも一度はみたことがあるのではないでしょうか?
簡単に実装できるライブラリは多くありますが、以下のような点で導入しづらいケースもあります。
- アニメーションタイプが限定されている
- カスタマイズが難しい
- 不要なコードが含まれている
- 複数のライブラリを使用する場合、ライブラリ同士が干渉して、正常に動作しない
自作すると自由度が高く、上のようなデメリットを回避できます。今回は、JavaScript(jQuery)を使用したスクロールアニメーションの実装方法を紹介します。
HTML・CSSを追加するだけで、アニメーションタイプを増やせたり、なるべく汎用性があるようにしました。
jQueryを使いますが、jQuery使わない場合も同じ考え方です。最後にJavaScriptのみで行うコードも記載したので、参考にしてみてください。
まずはライブラリを使って簡単に実装してみたい方は、下記の記事も参考にしてみてください!
【超簡単】JavaScriptライブラリaos.jsの使い方を解説!💡 コーディングの練習なら模写修行!
この記事の目次
単体でフェードインさせる
シンプルなスクロールアニメーションを実装します。要素が画面下部200pxに達したタイミングで0.6秒かけて、50px下の位置から、フェードアップさせます。
- HTMLを記述する
- CSSを記述する
- JavaScript(jQuery)を記述する
この流れで紹介します。
HTMLを記述する
<section class="single">
<h2>DEMO1</h2>
<div class="single-item u-fade-type-up js-scroll-trigger">
<img src="img/sample.jpg" alt="">
</div>
...
</div>
</section>
💡 class=”single-item"
レイアウトや見た目のスタイルを指定するためのクラスです。こちらのクラスには、アニメーション関連のCSSは指定しません。
💡 class=”u-fade-type-up"
アニメーション時のスタイルや動きを指定するためのクラスです。アニメーション関連のスタイルは全てこちらのクラスに指定します。「u-」は、「utility」の「u」です。
💡 class=”js-scroll-trigger"
トリガー用のクラスです。JavaScript側で要素が画面下部200pxに達したかを判定する際に必要となります。「js-」がついているクラスは、JavaScriptから操作するクラスなので、CSSの指定はしません。
CSSを記述する
/* レイアウトや見た目のスタイル */
/* ---------------------------- */
.single-item + .single-item{
margin-top: 80px;
}
/* アニメーションスタイル */
/* ---------------------------- */
/* アニメーション前 */
.u-fade-type-up{
transform: translateY(50px);
opacity: 0;
}
/* トリガー発火でis-activeを付与 */
.u-fade-type-up.is-active{
transition: .6s;
transform: translateY(0);
opacity: 1;
}
💡 アニメーション前
transform: translateY(50px);
で要素を50px下の位置に配置、かつopacity: 0;
で透明にしています。
💡 トリガー発火
要素が画面下部200pxに達したタイミングで、JavaScriptでis-active
クラスを付与します。0.6秒かけて、透明度と位置を元に戻します。
JavaScript(jQuery)を記述する
$(function () {
// aimation呼び出し
if ($('.js-scroll-trigger').length) {
scrollAnimation();
}
// aimation関数
function scrollAnimation() {
$(window).scroll(function () {
$(".js-scroll-trigger").each(function () {
let position = $(this).offset().top,
scroll = $(window).scrollTop(),
windowHeight = $(window).height();
if (scroll > position - windowHeight + 200) {
$(this).addClass('is-active');
}
});
});
}
$(window).trigger('scroll');
});
ページ内にjs-scroll-trigger
クラスが存在した場合、スクロールアニメーションの処理であるscrollAnimation関数を実行します。
少し長いので、分割して解説します。
💡 関数呼び出
// aimation呼び出し
if ($('.js-scroll-trigger').length) {
scrollAnimation();
}
scrollAnimation関数の呼び出しを行っています。
if文の条件$('.js-scroll-trigger').length
は、ページ内にjs-scroll-trigger
クラスが存在した場合「true」となり、関数呼び出しが行われます。js-scroll-trigger
クラスが存在しない場合は、呼び出されません。
js-scroll-trigger
クラスの有無を確認した上で、関数を実行するか否かを判断している理由は、scrollAnimation関数内にscrollイベントが含まれているからです。scrollイベントは比較的負荷の高い処理になので、ページ内にスクロール連動アニメーションが存在した場合にのみ、処理を実行しています。
💡 scrollAnimation関数
// aimation関数
function scrollAnimation() {
$(window).scroll(function () {
$(".js-scroll-trigger").each(function () {
let position = $(this).offset().top,
scroll = $(window).scrollTop(),
windowHeight = $(window).height();
if (scroll > position - windowHeight + 200) {
$(this).addClass('is-active');
}
});
});
}
$(window).trigger('scroll');
長くなるので、この中のコードをさらに分割して解説します。
$(window).scroll(function (){
…
});
スクロールに連動させるためには、常に処理に必要となる要素の位置を監視、取得しなければいけません。従って、scrollイベントを使用し、スクロール時に処理が行われるようにします。
$(".js-scroll-trigger").each(function(){
…
});
eachメソッドを使用し、全トリガー要素(class=”js-scroll-trigger”
が指定されている要素)に対して処理を適応させます。
.each()
は、指定した要素や配列、オブジェクトなどに対し、ループ処理を行うメソッドです。
$(".js-scroll-trigger")
に対して指定することで、サイト内の全トリガー要素に対して、以下の処理を適応させていることになります。
let position = $(this).offset().top,
scroll = $(window).scrollTop(),
windowHeight = $(window).height();
ここでは、「トリガーが画面下部 200px に達したか」を判定するために必要な情報を変数に格納しています。
.offset().top
は、ドキュメント最上部を基準に指定要素のY座標を戻り値として返します。従って、変数position
には各トリガーの垂直方向の位置が格納されます。
scrollTop()メソッドは、垂直方向のスクロール位置を戻り値として返します。従って、$(window)
に対して、.scrollTop()
を指定することで、ブラウザのスクロール位置を取得することが可能となります。
$(window).height()
ではウィンドウの高さを取得し、格納しています。
// 発火位置を「画面下部から200pxの位置」に設定する場合
if (scroll > position - windowHeight + 200){
$(this).addClass('is-active');
}
// 発火位置を「画面中央」に設定する場合はこちら
if (scroll > position - windowHeight / 2){
$(this).addClass('is-active');
}
「トリガーが画面下部 200px に達した」と判定した場合、is-active
クラスを付与しています。
今回のDEMOでは、発火位置を「画面下部 200px」に設定してますが、実装していると「画面中央」に設定したい場合も出てきます。
$(window).trigger('scroll');
リロード時などに、is-active
クラスが外れてしまうのを防いでいます。
今回は「処理に必要となる要素の位置情報を常に監視、取得し、その情報に基づいて、画面下部 200px に達したかを判定し、アニメーションを実行」しています。
しかし、仮に要素が画面下部 200px に達していた場合でも、リロードなど、再読み込みをかけてしまうと変数に格納されていた位置情報がリセットされてしまい、指定したはずのクラスが外れてしまいます。
従って、JavaScript ファイルが読み込まれた際に意図的にスクロールイベントを発生させ、各変数に再度位置情報を格納しています。
trigger()
メソッドは、任意のタイミングで指定したイベントを実行することができる jQueryメソッドで、引数にはイベントを指定します。
window
に対して、.trigger('scroll')
を指定することで実際にはスクロールを行なっていなくても、スクロールイベントを発生させることが可能になります。
一斉にフェードインさせる
今まで解説した内容は、要素単体でのフェードアップでしたが、ここでは、あるトリガーに達したら、「一斉にフェードインさせる」スクロールアニメーションを実装します。
JavaScriptはDEMO1と全く同じです。HTML・CSS を少し変更するだけで簡単に実装できます。DEMO1と異なる箇所のみ解説していきます。
HTMLを記述する
<section class="multiple">
<h2>DEMO2</h2>
<div class="multiple-list js-scroll-trigger">
<div class="multiple-item u-fade-type-up">
<img src="img/sample.jpg" alt="">
</div>
...
</div>
</section>
トリガーが画面下部 200px に達したタイミングでトリガー内の要素を一斉フェードインさせたいので、トリガーとなる div に対してjs-scroll-trigger
クラスを、フェードイン要素となるdivに対してu-fade-type-up
クラスを指定します。
CSS を記述する
/* レイアウトや見た目のスタイル */
/* ---------------------------- */
.multiple-list{
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.multiple-item{
width: 49%;
margin-top: 20px;
}
.multiple-item:nth-child(-n+2){
margin-top: 0;
}
/* アニメーションスタイル */
/* ---------------------------- */
/* アニメーション前 */
.u-fade-type-up{
transform: translateY(50px);
opacity: 0;
}
/* トリガー発火でis-activeを付与 */
.is-active .u-fade-type-up{
transition: .6s;
transform: translateY(0);
opacity: 1;
}
.is-active .u-fade-type-up:nth-child(2){transition-delay: .4s;}
.is-active .u-fade-type-up:nth-child(3){transition-delay: .8s;}
.is-active .u-fade-type-up:nth-child(4){transition-delay: 1.2s;}
.is-active .u-fade-type-up:nth-child(5){transition-delay: 1.6s;}
.is-active .u-fade-type-up:nth-child(6){transition-delay: 2s;}
@media screen and (min-width: 768px) {
.multiple-item{
width: 32%;
}
.multiple-item:nth-child(-n+3){
margin-top: 0;
}
}
💡 アニメーションスタイル
DEMO1の単体フェードインは、フェードイン要素にis-active
がつきましたが、一斉フェードインでは、フェードイン要素ではなく、親要素のトリガーにis-active
がつきます。アニメーション後のスタイル指定は.is-active .u-fade-type-up
のようになります。
各要素を0.4秒おきにフェードアップしたいので、transition-delay
を利用し、遅延実行しています。1つ目の要素は、トリガーにis-active
がついたと同時に実行され、2つ目の要素は0.4秒後、3つ目の要素は0.8秒後...に実行されます。
delayは、jQuery側で指定することも可能ですが、今回はCSS側で指定しています。基本的にスクロール連動は、限られた箇所でしか利用しないので、CSS側で指定した方が良いかなと思います。
jQueryを使わずにJavaScriptのみで実装する
// トリガー取得
const scrollTrigger = document.querySelectorAll('.js-scroll-trigger');
// aimation呼び出し
if (scrollTrigger.length) {
scrollAnimation(scrollTrigger);
}
// aimation関数
function scrollAnimation(trigger) {
window.addEventListener('scroll', function () {
for (var i = 0; i < trigger.length; i++) {
let position = trigger[i].getBoundingClientRect().top,
scroll = window.pageYOffset || document.documentElement.scrollTop,
offset = position + scroll,
windowHeight = window.innerHeight;
if (scroll > offset - windowHeight + 200) {
trigger[i].classList.add('is-active');
}
}
});
}
jQueryを利用せず、ネイティブのJavaScriptで実装する際は、上記のコードに変更してください。やっていることは、jQuery版と同じです。
コードに関して気になる方は、ご自身で調べてみてください。
応用例のサンプル
応用例としてサンプルをいくつか作成しました。
サンプルデモのアニメーションはJavaScriptは今まで解説したコードで、HTML・CSSのみ追加したものになります。このようにHTML・CSSをいじるだけで、カスタマイズも出来ます。
超実務向け!コーディングの練習が出来るサービス作りました 🎉
模写修行は実戦に沿った形で、コーディングの"練習"ができるサービスです。
こんな方におすすめ!
- 実務のレベル感を知りたい
- プロの制作フローを学びたい
- 何を考えながらコードを書くのか知りたい
- 基礎学習中、もしくは終えたばかり
- CSS設計やSCSSを使った書き方を学びたい
模写修行ではデザインデータ(FigmaとXD) / web上で見れる解説 / サンプルコードを提供しています。ご自身でデザインを見ながらコーディングに挑戦し、解説とサンプルコードで答え合わせ&さらに深く学ぶことができるサービスです。
他の書籍や教材との違いは、超初心者向け・学習用の書き方ではなく、実際の現場で通用する書き方や考え方にフォーカスしている点です。詳しくは下記の記事をご覧ください。
コーディング教材の【模写修行】は他の教材と何が違うのか?嬉しい声もいただいています!
自分のweb制作におけるコードの書き方、ファイル管理は模写修行さんから学ばせていただきました。独学の強い味方だと思いました。教材、メディアありがとうございました!
TwitterでDMいただきました!🙇
classの命名迷子・横並びレイアウト恐怖症だったけど、無料〜中級までいくつかやっていく中で、どんどん迷いが減っていって楽しかったです!解説記事もわかりやすい...!
Tweet
デザインきれいだし、解説とサンプルソースが付いて答え合わせしやすいところが良い。
Tweet
答え合わせ終わった。top-kvの実装方法に脱帽。そういうやり方があることを知れたことが大きい。。sass学びはじめたばかりなのでscssコードがとても参考になった。次からはscssでかく。
Tweet