スクロール量に応じたアニメーションを実現させるanimation-timelineを使って、面白い動きのあるウェブサイトを作ってみましょう。

animation-timelineはスクロール量に応じてアニメーションを制御できるCSSプロパティで、2024年3月現在は69.9%のブラウザをサポートしています。

Safariが非対応のためページ全体にゴリゴリ使うことは難しいですが、デザインに干渉しないような部分であれば使っても良いのかなーという印象ですね。

最新のブラウザの対応状況についてはCSS property: animation-timeline | Can I use…を参考にしてみてください。

サンプル

サンプルを見てみましょう。

See the Pen
スクロール量に応じて自由にアニメーションさせる
by イロイロデザインラボラトリ (@iroirodesignlab)
on CodePen.

スクロール量に応じてアニメーションしていますね!

…し、していませんか?

もし全然アニメーションしてないのであれば、今このページを見ているブラウザが非対応ということになります。Chrome、Edgeの場合は最新のバージョンに更新してください。

Safariの場合は2024年3月現在対応していませんので、ChromeかEdgeで見てみてください。

HTML

HTMLはこんな感じです。

<p>スクロールすると、いろいろな要素がアニメーションされます。</p>

<div class="progress-bar"></div>

<div class="content-image">
  <img src="https://source.unsplash.com/1920x1080" alt="" />
</div>

<div class="content-text">
  <h2>What is Lorem Ipsum?</h2>
  <p>
    Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially
    unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry.
  </p>
</div>

<div class="content-image">
  <img src="https://source.unsplash.com/1920x1080" alt="" />
</div>

<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
  <li>E</li>
  <li>F</li>
  <li>G</li>
</ul>

<p>ページの最後です。</p>

特別なことはしてません。普通にコーディングするだけでだいじょうぶです。

CSS

CSSはSCSSを使っています。

.progress-bar {
  width: 0;
  height: 100%;
  background: #7ed6df;
  position: fixed;
  top: 0;
  left: 0;
  animation-name: flex-bar;
  animation-timeline: scroll();
  z-index: -1;

  @keyframes flex-bar {
    100% {
      width: 25%;
      transform: rotate(25deg) translate(75%, 25%);
    }
  }
}

.content-image {
  margin: 50% auto;
  max-width: 60rem;
  animation-name: image-fadein;
  animation-timeline: view();

  img {
    width: 100%;
  }

  @keyframes image-fadein {
    0% {
      opacity: 0;
      filter: blur(1rem);
      transform: scale(0.9);
    }

    50% {
      opacity: 1;
      filter: blur(0);
      transform: scale(1);
    }
  }
}

.content-text {
  padding: 2rem;
  margin: 50% auto;
  max-width: calc(60rem - 4rem);
  animation-name: box-color;
  animation-timeline: view();

  @keyframes box-color {
    75% {
      background: #303030;
      color: #ffffff;
    }
  }
}

ul {
  margin: 50% auto;
  list-style: none;
  display: flex;
  justify-content: center;
  gap: 10rem;
  animation-name: letter-space;
  animation-timeline: view();
  mix-blend-mode: color;
  overflow: hidden;

  li {
    font-size: 2rem;
  }

  @keyframes letter-space {
    100% {
      gap: 1rem;
      font-weight: bold;
    }
  }
}

キーとなるのはanimation-timelineで、@keyframesで動きを作っています。

animation-name

animation-nameはアニメーションさせる名前を付けるプロパティです。名前は任意ですので分かりやすければ何でもだいじょうぶです。

animation-timeline

アニメーションさせる方法を指定することができます。指定できるのはscrollとviewで、いずれも「どのタイミングでアニメーションを開始させるか」を指定します。

scroll

scrollはページ全体のスクロール量に応じてアニメーションさせることができます。例えば下記のような「スクロールしたらスクロール量に応じたプログレスバーを表示させる」ことができたり、「スクロールしたら背景色とテキストのカラーを変えたりする」みたいな使い方ができます。

See the Pen
スクロール量に応じて自由にアニメーションさせる:プログレスバー
by イロイロデザインラボラトリ (@iroirodesignlab)
on CodePen.

また、scrollにはroot(ページ全体)かself(指定した要素のみ)を指定することができるので、「指定した要素だけ背景色を変える」ような使い方もできます。

.hoge {
  animation-timeline: scroll(self);
}

view

viewはスクロールして要素が見える場所(ビューポート)に入ったらアニメーションが開始されて、スクロールして見えなくなったらアニメーションが終了します。

例えば下記のような「スクロールして見える場所に入ったら背景色を変える」ことや「画像をフェードインさせる」ような使い方ができます。

See the Pen
スクロール量に応じて自由にアニメーションさせる:背景色を変えたり画像をフェードインさせたり
by イロイロデザインラボラトリ (@iroirodesignlab)
on CodePen.

@keyframes

@keyframesにはアニメーションがどのように始まりどのように終わるかを0%から100%までの数字で指定します。

例えばviewの場合はスクロールして見えなくなったら効果が消えるので、ページの中央あたりで表示したいなら50%くらいを目安にアニメーションを終了させることで効果的な演出ができると思います。

@keyframes hoge {
  50% {
    opacity: 1;
  }
}

JavaScript

今回はJavaScriptを使っていませんが、setTimeoutで遅延させたりすることでより効果的なアニメーションを作ることができますので、ぜひ色々試してみてください。