スクロールしたら要素がふわっとフェードインするアニメーションを、jQueryを使わず生のJavaScript(Vanilla JS)で実装したい。
本記事では、下のようにスクロールすると要素がフェードインするアニメーションの実装方法を解説します。
生のJavaScript(Vanilla JS)を使った方法なので、jQueryが使えない現場で役に立つかと思います。
See the Pen Untitled by たけち (@kwxteqls-the-scripter) on CodePen.
【JavaScript】スクロールで要素をフェードインさせる方法
JavaScriptを使って、スクロールで要素をフェードインさせる方法を解説します。
ざっくりとした実装のポイントと方針は、次の通りです。
こちらを頭の片隅に置きながら、まずはHTMLとCSSで見た目を作りましょう。
見た目の作成
<header class="header">
<div class="header__inner">
<h1 class="header__logo">Let's Scroll!!</h1>
</div>
</header>
<div class="mainView">
<p>Main View</p>
<div class="scrollDown"><span>Scroll</span></div>
</div>
<main>
<div class="boxes inner">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</main>
body{
color: #333;
background-color: #fff;
}
.inner{
max-width: 1200px;
width: 100%;
margin-right: auto;
margin-left: auto;
padding: 0 20px;
}
.header{
width: 100%;
height: 50px;
display: flex;
align-items: center;
background-color: #223a70;
position: fixed;
left: 0;
top: 0;
z-index: 100;
}
.header__inner{
padding: 0 20px;
}
.header__logo{
font-size: 20px;
color: #fff;
text-transform: uppercase;
}
.mainView{
height: calc(100vh - 50px);
display: flex;
align-items: center;
justify-content: center;
margin-top: 50px;
position: relative;
}
.mainView p{
font-size: 28px;
font-weight: bold;
}
.scrollDown{
position: absolute;
bottom: 80px;
right: 50%;
animation: scrollDown 1s ease-in-out infinite;
}
@keyframes scrollDown{
0% {bottom: 10%}
50% {bottom: 15%}
100% {bottom: 10%}
}
.scrollDown span{
position: absolute;
left: -25px;
bottom: 10px;
font-size: 0.8em;
letter-spacing: 0.05em;
writing-mode: vertical-rl;
}
.scrollDown::before{
position: absolute;
content: "";
width: 1px;
height: 20px;
background-color: #333;
bottom: 0;
right: -6px;
transform: skew(-30deg);
}
.scrollDown::after{
position: absolute;
content: "";
width: 1px;
height: 60px;
background-color: #333;
bottom: 0;
right: 0;
}
.boxes{
display: grid;
grid-template-columns: repeat(2, 1fr);
column-gap: 20px;
row-gap: 80px;
margin-top: 100px;
}
.box {
aspect-ratio: 16 / 9;
background-color: #dedede;
}
この時点では、フェードインの対象要素(.box)にはアニメーションが付いていません。
See the Pen scroll-animation_nonJS by たけち (@kwxteqls-the-scripter) on CodePen.
要素を非表示にする
要素(.box)のopacityを0、visibilityをhiddenにして非表示にしましょう。
ついでに、遅れを表現するためのtransitionと、下から表示させるためにtransformでずらしておきます。
なお、display: noneでも非表示にできますが、transitionが効かないのでおすすめしません。
.box {
/*追加*/
opacity: 0;
visibility: hidden;
transition: all 1s;
transform: translateY(150px);
}
表示用のクラスを用意する
JavaScriptで表示を切り替える用に、クラスを準備しておきましょう。
CSSに、下記を追記してください。
この「is-activeクラス」をJavaScriptで付与することで、要素をフェードインさせます。
.is-active {
/*要素を表示させる*/
opacity: 1;
visibility: visible;
/*元の位置に戻す*/
transform: translateY(0);
}
これで見た目は完成しました。
JavaScriptの実装
JavaScriptで、フェードインの動きを付けていきましょう。
スクロールイベントの作成
アニメーションのトリガーは「スクロール」なので、まずはスクロールのイベントリスナーを記述しましょう。
window.addEventListener('scroll', function(){
});
イベント発生のタイミングを考える
JavaScriptを実装するにあたって考えるべきは、イベント発生のタイミング、つまり「いつis-activeクラスを付与するか?」ですね。
答えは、スクロールして、要素(.box)が画面内入った瞬間です。
では、どうやって「要素が画面内に入ってきたよ」とコンピューターに知らせることができるでしょう?
これには、次の3つの数値が必要となります。
そして、それぞれ下記のプロパティで取得可能です。
上記を図で表すと、次のような関係になります。
つまり、上の3つの数値で下記が成り立てば、画面内に要素が入ってきたことになります。
- スクロール量 + 画面の高さ > 要素までの高さ
JavaScriptを記述する際には、if文を使って、上記が成り立つときだけ.boxにis-activeクラスを付与するようにします。
なお、.boxは複数あるので、querySelectorAllで全て取得してforEachで回すことで個別の値を取ることができます。
window.addEventListener('scroll', function(){
// スクロール量を取得
const scroll = window.scrollY;
// 画面の高さを取得
const windowHeight = window.innerHeight;
// すべての.boxを取得
const boxes = document.querySelectorAll('.box');
boxes.forEach(function(box) {
// boxまでの高さを取得
const distanceToBox = box.offsetTop;
// 下記条件が成り立つときだけboxにis-activeクラスを付与する
if(scroll + windowHeight > distanceToBox) {
box.classList.add('is-active');
}
});
});
JavaScriptのコードは以上です。
スクロールして画面内に.boxが入った瞬間に下からフェードインするアニメーションが完成しました。
See the Pen Untitled by たけち (@kwxteqls-the-scripter) on CodePen.
まとめ
今回はJavaScriptを使って、要素をふわっとフェードイン表示させる方法を解説しました。
もし「JavaScriptは難しい…」と感じた場合は、より簡単なjQueryを使った実装方法も解説しているので、あわせて活用してください。