スクロールアニメーションに革命!CSSだけで実装する方法を解説します【JavaScriptなし】
目次
はじめに
こんにちは!NNCの大土です。
今回はスクロールアニメーションについてのお話です。
WEBサイト構築時、スクロールに連動して要素に変化を起こしたり、少し変わった動きをつけたいな、という時に悩む方も多いのではないでしょうか?
また、そういった複雑な動きは従来JavaScriptを使って実装することがほとんどでしたが、
CSSで表現できるアニメーションの幅が近年増えてきています!
JavaScriptで細かいアニメーションを作るのは苦手だな…という方でもCSSでリッチなアニメーション表現を作成することができますので、ぜひ参考にしていただけたら嬉しいです。
作成できるアニメーション例
まずは、実際にどのようなスクロールアニメーションが作れるのかサンプルを見てみましょう。
このように、スクロールに応じてコンテンツのフェードインや回転、視差効果など様々なアニメーション表現を行うことができます。
詳しい設定方法
上のサンプルのようなスクロールに連動したアニメーションを作る場合、大きく2つの考え方があります。
スクロール範囲内全体でのアニメーション
一つ目は、スクロール開始位置から終了位置までの間で、スクロールに連動したアニメーションを設定する、というものです。
図で表すと、こんなイメージです。
例として、以下のようなスクロールに連動して伸びるバーを挙げてみます。
スクロールするたびにバーが横に伸びていく仕組みで、記事系のページなどで残りどの程度の情報が書いてあるかを把握できます。
See the Pen Untitled by studio-nnc (@studio-nnc) on CodePen.
まずdiv要素に対してanimationプロパティを設定します。
一定の速度でアニメーションさせ、@keyframes以下でwidthの値を0から100%に変化させています。
そこに加えてanimation-timeline: scroll();というプロパティ・値の命令を出すことで、
一番上から一番下までスクロールを行う間にアニメーションを設定することができます。
可視領域内でのアニメーション
二つ目は、画面の可視領域(スクロールポート)の中でスクロールに伴うアニメーションを設定するという考え方です。
アニメーションさせたい要素が画面上で表示されているときにアニメーションを起こします。
例として、スクロールをするたびに円の色が変わるアニメーションを見てみましょう。
See the Pen Untitled by studio-nnc (@studio-nnc) on CodePen.
上の例ではスクロールして円が表示されたら、円の色がグレーから黒にだんだんと変化しています。
こちらは、circleというクラスをつけたdiv要素にanimationプロパティを命令し、一定の速度で円の背景色を変えています。
同時にanimation-timeline: view(); というプロパティと値を命令することで、
円が画面上に表示されたときにスクロールに連動してアニメーションを起こすように設定、
またanimation-range: cover; で円が画面上に表示されてから完全に出ていくまでの間にアニメーションするよう設定しています。
animation-rangeプロパティの値はいくつかあり、使い分けることで
具体的にどのタイミングでアニメーションを開始・終了させるのか設定することができます。
値については以下を参照してください。
cover
アニメーションさせたい要素が、
スクロールポートに入ってきてから完全に出るまで
例:円がスクロールポートに入ってから完全に出るまでの間に、赤から青へ変化
See the Pen Untitled by studio-nnc (@studio-nnc) on CodePen.
contain
アニメーションさせたい要素が、
スクロールポートに完全に収まっている間
例:円がスクロールポートに完全に収まっている間に、赤から青へ変化
See the Pen Untitled by studio-nnc (@studio-nnc) on CodePen.
entry
アニメーションさせたい要素が、
スクロールポートに入った瞬間から完全に収まるまでの間
例:円がスクロールポートに入った瞬間から完全に収まるまでの間に赤から青へ変化
See the Pen Untitled by studio-nnc (@studio-nnc) on CodePen.
exit
アニメーションさせたい要素が、
スクロールポートから出た瞬間から完全にスクロールポートを出るまでの間
例:円がスクロールポートから出た瞬間から完全に出るまでの間に赤から青へ変化
See the Pen Untitled by studio-nnc (@studio-nnc) on CodePen.
entry-crossing
アニメーションさせたい要素が、
スクロールポートの開始のラインの上に重なっている(横切っている)間
例:円がスクロールポートの開始のラインを横切っている間に赤から青へ変化
See the Pen Untitled by studio-nnc (@studio-nnc) on CodePen.
exit-crossing
アニメーションさせたい要素が、スクロールポートの終了のラインの上に重なっている(横切っている)間
例:円がスクロールポートの終了のラインを横切っている間に赤から青へ変化
See the Pen Untitled by studio-nnc (@studio-nnc) on CodePen.
ブラウザ対応状況
2024年4月現在、animation-timelineプロパティについてはSafari・Firefoxの環境ではブラウザ未対応となっております。
全ブラウザに対応されるまでにしっかりと理解をして、対応後すぐに使いこなせるようになりましょう!
https://caniuse.com/mdn-css_properties_animation-timeline
作成事例
さて、ここからは具体的なアニメーションの事例をご紹介したいと思います。
実装イメージとサンプルコードを載せていますので、コピペして使ったり、ご自由に改変してご活用いただいてもOKです!
要素のカラーを変更する / ヘッダー背景透過
ページトップからスクロールした時にヘッダーの背景色を透過させているアニメーションです。
See the Pen Untitled by studio-nnc (@studio-nnc) on CodePen.
header要素に対してanimationを設定しておき、@keyframes以降で具体的なアニメーションの命令を出します。
少しスクロールしたときにすぐに背景色を切り替える仕様にするため、アニメーションが1%の段階で背景色と不透明度を変更しています。
要素の不透明度を上げる / フェードイン表現
opacityを0→1にすることで徐々に要素が表示されるフェードインのようなアニメーション設定です。
応用してフェードアウトなどの表現も可能です。
スクロールに応じたアニメーションなので、要素をふわっと表示させるような表現をしたい場合はJavaScriptを使うとよさそうです。
See the Pen Untitled by studio-nnc (@studio-nnc) on CodePen.
fade-inというクラスをつけたsection全体にanimationを設定しています。
sectionが可視範囲に入るまではopacity:0に設定しておき、入ってから要素全体が収まるまでの間にopacity:1に変化させることで、
徐々に表示されるフェードインの効果を表しています。
要素を移動させる / 視差効果を使った装飾
animationを使って要素のpositionの位置を切り替えることで視差効果をつけています。
スクロールするたびにロケットやスワンボートを動かすちょっと可愛いアニメーションが表現できます。
See the Pen Untitled by studio-nnc (@studio-nnc) on CodePen.
img要素を用意し、下から上、右から左へpositionの位置を変えるアニメーションを設定しています。
スワンボートはスクロールごとに細かく動かすため10%刻みで位置を変更し、
一方ロケットはpositionの数値を25%以降からぐっと下げることによってロケットが加速していく感じを表現しています。
また、ロケットのanimationの命令にはforwardsを入れることで、アニメーション終了時の状態をキープするよう設定しています。
(これを無くしてしまうとスクロール中盤に画像がブレて表示されてしまいます)
要素を回転させる / 時計の針
transform:rotateを使ってスクロールするたびに時計の針を進めるようなアニメーションです。
transformプロパティについてよく知らないという方は、こちらの記事をチェックしてみてください!
See the Pen Untitled by studio-nnc (@studio-nnc) on CodePen.
このアニメーションでは、時計本体・長針・短針3つをimgでそれぞれ用意し、長針と短針にanimationを設定して角度を回転させています。
時計の針に対してanimationを設定しているので、針が完全に見えなくなるとアニメーションが終了します。
ポイントとしてはtransform-originプロパティで回転する起点位置を決めておくことです。
長針はbottomに、短針はあらかじめ角度をつけているのでleft bottomを起点にします。
そうしないと針自体が回転してしまうことになります(経験談)。
ご紹介したサンプルのほか、
以下のサイトでは、さらに高度なアニメーションの実装例が紹介されています!
こんな表現もCSSでできるの・・・?と驚きがいっぱいです。
CSS・JavaScriptそれぞれの実装時のデモも紹介されておりますのでぜひご覧ください。
Scroll-driven Animations
https://scroll-driven-animations.style
CSSプロパティまとめ
今回登場したプロパティや値の種類などをまとめておきます。
animationプロパティについては、こちらの記事にてさらに詳しく解説しています!
プロパティ名 | 説明 | 例 |
animation | アニメーション開始〜終了までに 何をどのように変化させるか命令する | animation: scrollAnime linear →scrollAnimeという名前をつけ、 一定の速度でアニメーションさせる |
animation-timeline | スクロールに連動したアニメーションを設定 | animation-timeline: scroll() →スクロールできる範囲内でのアニメーションを設定 animation-timeline: view() →可視範囲内でのアニメーションを設定 |
animation-range | どのタイミングでアニメーションを 開始・終了させるか設定 | animation-range:cover →可視範囲に入ってきてから完全に出るまで :contain →可視範囲に完全に収まっている間 :entry →可視範囲に入った瞬間から完全に収まるまでの間 :exit →可視範囲から出た瞬間から完全に出るまでの間 :entry-crossing →可視範囲の開始ラインの上に重なっている間 :exit-crossing →可視範囲の終了のラインの上に重なっている間 |
まとめ
今回の記事ではCSSだけで実装できるスクロールアニメーションのご紹介をしました。
animation関連のプロパティの使い分けや違いの判断が難しいところですが、
うまく活用すれば表現のバリエーションを増やすことができますので、ぜひ参考にしていただければ嬉しいです!
STUDIO NNC 合同会社ではさまざまなアニメーション表現を得意としています。
制作のご相談がございましたら、お気軽にお問い合わせフォームよりご連絡ください。
記事の執筆にあたり参考にさせていただいたサイト/記事はこちらです。
ありがとうございました!
・https://qiita.com/degudegu2510/items/9fa70a8b5284e37f2fe3
・https://ics.media/entry/230718/
・https://scroll-driven-animations.style/
・https://developer.mozilla.org/ja/docs/Web/CSS/animation-timeline
・https://developer.mozilla.org/ja/docs/Web/CSS/animation-range