【CSSだけ】続編: スクロールに連動して要素が動く!新概念をつかった視差エフェクトを作る方法[ScrollTimeline, ViewTimeline]

【CSSだけ】スクロールに連動して要素が動く!新概念をつかった視差エフェクトを作る方法[ScrollTimeline, ViewTimeline]
今回も、CSSアニメーションの新概念「ScrollTimeline」と「ViewTimeline」を組み合わせた記事の続編です!

以前の記事では、スクロールに応じて単純に画像が出現する、という内容を書きました。
今回はそれプラス、「画像だけではなく、任意の他の要素」一緒に連動して動かす方法について書いていきたいと思います。
つまり、これを応用すると「スクロール量に応じたパララックスエフェクト」なんかも作れる様になる、ということですね。

スクロールに反応して画像が出現 + 他の要素も連動して動く

早速ですが今回も、まずは次の動画をご覧ください。

↑こちらの動画ですが、「ページのスクロールに応じて」セクションごとにトラッドな車の画像が出現するのですが、
その際に、ガレージのシャッターが開く様な動きも連動して行われています。

実はこちらも、以前の記事のサンプルと同じく、「CSSだけ」で出来ています。
CSSアニメーションの新概念「ScrollTimeline」と「ViewTimeline」を組み合わせると、
こういう視差をともなったエフェクト、視覚効果もつくることができる、というもうひとつのサンプルになります。

以前の記事では、
・画像のimgタグそのものにCSSの clip-path が変化するアニメーションを設定
・それを「ScrollTimeline」と「ViewTimeline」を利用して動かす
・あたかもシャッターが開いて出現する様な効果が得られる

↑こういったアプローチの内容を書きましたが、

今回は
・画像のimgタグとは異なる要素を用意
・その要素の背景画像にシャッターの画像を適用
・それらを「ScrollTimeline」と「ViewTimeline」と連動させることで、スクロール量に反応して、画像とシャッターがどちらも連動して動く

↑ということをしています。コードのサンプルなどは次のセクションに続きます。

実際に動かせるサンプル

次のリンクに、
上のセクションの動画と同じ挙動をするサンプルを用意しました。

スクロールに応じて反応する、画像とシャッターの動作、CSSだけで視差効果が生まれる様子を、ぜひ実際にお試しください!

スクロールに連動して要素が動く、視差エフェクトのサンプル

コードのサンプル_html側

htmlのサンプルコードです。以前の記事との差分は、
画像出現セクションに、スクロールと連動して動くspan要素があたらしく付与されている点だけです。
本文は長いので…(中略)…としています。
※以前の記事同様、画像は適宜、16:9の画像を用意して当ててみれば動きます。

<div class="container">
  <section>
    <div class="common-inner">
      <h2 class="common-title">Driving Trad Vibes</h2>
      <p class="common-text">
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras non nunc
        lorem. Suspendisse tincidunt, elit quis volutpat volutpat, sapien libero
        fermentum felis, non luctus ipsum lectus quis lorem. Aenean euismod
        neque in nulla scelerisque, in faucibus magna dignissim. Duis placerat
        dolor leo, ut porta metus dapibus quis. Ut diam massa, commodo quis est
        id, eleifend fringilla ipsum. Suspendisse et ex a sem pharetra ornare.
        Proin venenatis laoreet nisl, nec laoreet mauris tincidunt in. In eget
        nisl commodo, hendrerit enim vitae, interdum ex. In rhoncus porttitor
        ornare. Pellentesque suscipit neque enim, ut auctor urna sollicitudin
        eu. Curabitur ullamcorper mollis malesuada.
     ...(中略)
      </p>
    </div>
  </section>

  <section class="appear-section">
    <div class="appear-body">
      <img 
        class="appear-image"
        src="./assets/images/sample-a.jpg"
        alt="sample"
        width="1600"
        height="900"
      >
      <span class="appear-object"></span>
    </div>
  </section>

  <section>
    <div class="common-inner">
      <h2 class="common-title">Trad Cars: The Fashion of the Road</h2>
      <p class="common-text">
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras non nunc
        lorem. Suspendisse tincidunt, elit quis volutpat volutpat, sapien libero
        fermentum felis, non luctus ipsum lectus quis lorem. Aenean euismod
        neque in nulla scelerisque, in faucibus magna dignissim. Duis placerat
        dolor leo, ut porta metus dapibus quis. Ut diam massa, commodo quis est
        id, eleifend fringilla ipsum. Suspendisse et ex a sem pharetra ornare.
        Proin venenatis laoreet nisl, nec laoreet mauris tincidunt in. In eget
        nisl commodo, hendrerit enim vitae, interdum ex. In rhoncus porttitor
        ornare. Pellentesque suscipit neque enim, ut auctor urna sollicitudin
        eu. Curabitur ullamcorper mollis malesuada.
     ...(中略)
      </p>
    </div>
  </section>

  <section class="appear-section">
    <div class="appear-body">
      <img 
        class="appear-image"
        src="./assets/images/sample-b.jpg"
        alt="sample"
        width="1600"
        height="900"
      >
      <span class="appear-object"></span>
    </div>
  </section>

  <section>
    <div class="common-inner">
      <h2 class="common-title">A Timeless Journey of Heart and Soul...</h2>
      <p class="common-text">
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras non nunc
        lorem. Suspendisse tincidunt, elit quis volutpat volutpat, sapien libero
        fermentum felis, non luctus ipsum lectus quis lorem. Aenean euismod
        neque in nulla scelerisque, in faucibus magna dignissim. Duis placerat
        dolor leo, ut porta metus dapibus quis. Ut diam massa, commodo quis est
        id, eleifend fringilla ipsum. Suspendisse et ex a sem pharetra ornare.
        Proin venenatis laoreet nisl, nec laoreet mauris tincidunt in. In eget
        nisl commodo, hendrerit enim vitae, interdum ex. In rhoncus porttitor
        ornare. Pellentesque suscipit neque enim, ut auctor urna sollicitudin
        eu. Curabitur ullamcorper mollis malesuada.
     ...(中略)
      </p>
    </div>
  </section>

  <section class="appear-section">
    <div class="appear-body is-third">
      <img 
        class="appear-image"
        src="./assets/images/sample-c.jpg"
        alt="sample"
        width="1600"
        height="900"
      >
      <span class="appear-object"></span>
    </div>
  </section>
</div>

コードのサンプル_css側

続いて、CSSのサンプルです。こちらも以前の記事との差分は少しだけで、
・あたらしく追加されたspan要素 .appear-object に関するスタイルが末尾に追加
・スクロールと連動する仕組みを view-timeline-name で親要素.appear-body側に定義
・スクロールと連動して動くアニメーション moveWithAppearToUp の定義

↑しているくらいの変更になります。

(※やや全体が長めなので、一旦メディアクエリ(スマホサイズのスタイルなど)は省いてます)

基本的な動きは 以前の記事 と同じですので、詳しい解説はそちらと見比べてみると、理解しやすいかと思います。

/* 基本構造。必ずしもこの限りでなくても動きます */
.common-inner {
  margin: 30rem auto 5rem;
  width: 1080px;
}
.common-title {
  color: rgb(250, 238, 155);
  font-family: serif;
  font-size: 3rem;
  font-weight: 500;
  text-align: center;
}
.common-text {
  color: #fff;
}

/* あたらしく付与したspan要素が動くアニメーション。スクロールと連動して動きます */
@keyframes moveWithAppearToUp {
  from {
    top: 0;
  }
  to {
    top: -190%;
  }
}

/* 画像のセクションの親要素 */
.appear-body {
  background: #323232;
  display: flex;
  height: 500px;
  /* overflow: hidden を使うと動作しなくなるため */
  /* mask-image を使って画像をマスクする         */
  mask-image: linear-gradient(rgb(0, 0, 0), rgb(0, 0, 0));
  position: relative;
  width: 100%;
  /* スクロールと連動する仕組みはここで定義 */
  view-timeline-name: --frontToAppearMove;
  view-timeline-axis: block;
}
/* 末尾のセクションだけクラスつけて調整_必須ではない */
.appear-body.is-third {
  margin: 0 auto 30rem;
}

/* 画像セクションに奥行きを与えるための擬似要素 */
.appear-body::before {
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.9);
  content: "";
  display: block;
  height: 3px;
  left: 0;
  position: absolute;
  top: -3px;
  width: 100%;
  z-index: 200;
}
.appear-body::after {
  box-shadow: 0 -3px 10px rgba(0, 0, 0, 0.9);
  content: "";
  display: block;
  height: 3px;
  left: 0;
  position: absolute;
  bottom: -3px;
  width: 100%;
  z-index: 200;
}

/* 画像セクション */
.appear-image {
  aspect-ratio: 16 / 9;
  display: block;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  position: relative;
  width: 100%;
}
.appear-object {
  /* span要素に付与する背景画像。適宜、16:9の画像を適用すれば動きます */
  background: url(/sample-silver-wall.jpg) no-repeat 0 0/cover;
  display: block;
  height: 100%;
  top: -50%;
  left: 0%;
  position: absolute;
  width: 100%;
  z-index: 100;

  /* ここから先が新要素! */
  animation: linear moveWithAppearToUp both;
  animation-timeline: --frontToAppearMove;
  /* ここから上が新要素! */
}

現時点での対応状況とポリフィル(補完して動かすJS)

こちらの
新しい概念「ビュータイムライン(ViewTimeline)」と「スクロールタイムライン(Scroll Timeline)」ですが、

とても「新しい」ということもあり、この記事を書いている時点での各ブラウザの対応状況は次の通りです。
・Chrome 115 以上
・Edge 115 以上
・Firefox 未対応
・Safari 未対応

…の状況です。

ですが!以前も書いた通り
ポリフィル(補完して動かすJS)もありまして、
次のJSを、動かしたい対象のhtml内に読み込んであげれば
未対応のブラウザでも動作させることが可能
です!
flackr/scroll-timeline

読み込ませ方は、上記リンク先ページの Read me 部分に記載があります。

ViewTimeline(ビュータイムライン)のMDNでの解説ページ

こちらも以前の記事 に書いたのと同じことですが、
ご存知、MDNにもすでに、ViewTimeline(ビュータイムライン)の解説ページがあります。
正直、必要な仕様の理解としては、MDNのこのページを読めば大体わかるかと思います。

view-timeline – CSS: カスケーディングスタイルシート | MDN

↑CSSのサンプルのセクションで書いた、
view-timeline-name, view-timeline-axis に関する説明も掲載されています。
一読すると、理解が深まるかと思います。

この記事のまとめ

今回は、Web制作・Webデザインの世界における
新しい概念「スクロールタイムライン(Scroll Timeline)」と、
もうひとつの新概念である「ビュータイムライン(ViewTimeline)」を組み合わせるとどんな事ができるか?
と言うことの第三弾として、
「ページのスクロールに応じて」セクションごとに画像が、シャッターが開く様なエフェクト(今回は、これが画像とはことなる要素)をともなって出現する例をもとに、記事を書きました。

いかがでしたでしょうか。記事内でも書いた通り、
以前の記事 と基本原理はほぼ同じですので、
見比べながら確認すると、理解しやすいかと思います。

今後も、「スクロールタイムライン(Scroll Timeline)」と「ビュータイムライン(ViewTimeline)」のすばらしい魅力が伝わりやすいような
記事を書いていきたく思ってますので、またぜひぜひ、続編をお待ちください。

この記事が皆さんのより良いWeb制作体験につながれば、嬉しく思います。

※この記事は内容の品質向上を目的に、随時更新を行う場合があります。


参考文献等:
Scroll-driven-animations(https://scroll-driven-animations.style/) – Copyright (c) Bramus (https://github.com/bramus), Chrome Developer Relations Engineer at Google
┗ License – https://www.apache.org/licenses/LICENSE-2.0.txt (Apache License Version 2.0)
scroll-timeline.js – Copyright (c) Robert Flack (https://github.com/flackr)
┗ License – https://www.apache.org/licenses/LICENSE-2.0.txt (Apache License Version 2.0)

この記事をシェアする: