今回はその記事でも登場した「ViewTimeline」について、もうすこし焦点をあてて書いていきたいと思います。
スクロールに反応して画像が出現!
早速ですが今回も、まずは次の動画をご覧ください。
↑この動画ですが、「ページのスクロールに応じて」セクションごとにトラッドな車の画像が、
シャッターが開く様なエフェクトをともなって出現します。
実はこちらも、前回の記事のサンプルと同じく、「CSSだけ」で出来ています。
CSSアニメーションの新概念「ScrollTimeline」と「ViewTimeline」を組み合わせると、
こういう視差をともなったエフェクト、視覚効果もつくることができるんです。
実際に動かせるサンプル
次のリンクに、上記のセクションでご紹介した
CSSアニメーションの新概念「ScrollTimeline」と「ViewTimeline」を組み合わせた、
動画と同じ挙動をするサンプルを用意しました。
スクロールに応じて、CSSだけで視差効果が生まれる様子を、ぜひ実際にお試しください!
コードのサンプル_html側
htmlのサンプルコードです。
本文は長いので…(中略)…としています。
文章のセクション → 画像出現セクション
の順番で3セット続きます。文章のセクションの内容は、ある程度の長さがあれば何でも良いです。
※画像は適宜、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" > </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" > </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" > </div> </section> </div>
コードのサンプル_css側
続いて、CSSのサンプルです。大まかな説明はコメントアウトで記載しました。
(※やや長めなので、一旦メディアクエリ(スマホサイズのスタイルなど)は省いてます)
重要な点は、末尾の方にある
view-timeline-name,
view-timeline-axis,
animation-timeline,
animation-range
↑このあたりです。
コードの後に続いて補足を記載します。
/* 基本構造。必ずしもこの限りでなくても動きます */ .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; } /* 画像がシャッターが開く様に出現するアニメーション。clip-pathを使い画像をマスクしている。 */ @keyframes imageToAppear { from { opacity: 0; clip-path: inset(100% 0% 100% 0%); } to { opacity: 1; clip-path: inset(0% 0% 0% 0%); } } /* 画像のセクションの親要素 */ .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%; } /* 末尾のセクションだけクラスつけて調整_必須ではない */ .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%; /* ここから先が新要素! */ /* まずはview-timeline-nameとしてスクロールの基準となる要素を定義 */ view-timeline-name: --imageToAppear; /* view-timeline-axisはスクロールの基準となる方向を定義 */ view-timeline-axis: block; /* アニメーション自体はこれまでのCSSアニメーション指定と同様の方法 */ animation: linear imageToAppear both; /* アニメーションが動作する概念を「時間軸」ではなく「スクロール軸」にする */ animation-timeline: --imageToAppear; /* アニメーションが動作する範囲。基準要素のどこから動き出してどこまでで動きが完了するか */ animation-range: entry -50% cover 50%; /* ここから上が新要素! */ }
cssの補足
基本的にはコメントアウトに記載の通りですが、
1. まずは view-timeline-name としてスクロールの基準となる要素を定義する。
2. 続いて view-timeline-axis として、スクロールの基準となる方向を定義。この場合は block を指定しているので、縦方向のスクロールが基準となる。
3. アニメーション自体はこれまでのCSSアニメーション指定と同様の方法。「animation: イージング 名前 実行の前後の挙動;」の順で指定しています。
4. そして animation-timeline を使い、アニメーションが動作する概念を「時間軸」ではなく「スクロール軸」に設定。
5. animation-range で、基準要素のどこから動き出してどこまでで動きが完了するかを設定しています。
なお、ViewTimeline(ビュータイムライン)は、animation-timeline: view(); と記述することでも使用ができます。
ただし、
上記の 1. view-timeline-name の様にして「名前付きのViewTimeline(ビュータイムライン)」にしてあげると、
同一ページ内で複数のスクロール基準要素を定義できたり、なにかと使い勝手が良くなります。
「名前付きのViewTimeline(ビュータイムライン)」は、上記の例の様に
–name(ハイフンを先頭に2つ付ける、css変数と同じ記法)
の形式で定義します。
ViewTimeline(ビュータイムライン)ってなにもの?
ここまでのセクションを読んで、だいたい何者なのかは想像がついてきたかと思いますが、
ViewTimeline(ビュータイムライン)というのは
「ScrollTimeline(スクロールタイムライン)が反応する領域」のようなものになります。
似ているのは、IntersectionObserverの概念です。
あれと同じ様に、定義しているのは「反応する領域」です。
「ViewTimeline(ビュータイムライン)として定義した要素」が、
「ビューポートに入っているかどうか」を基準にして
「ScrollTimeline(スクロールタイムライン)が反応する」領域を作っている。
そういった概念になります。
…と思うかもしれません。私も最初は ??? という感想でした。
より詳しい説明は、今後の記事でも書いていきます。
まずは「そういうものがあるんだな〜」くらいに興味を持ってもらえたら、この記事の価値があります。
現時点での対応状況とポリフィル(補完して動かす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)」を組み合わせるとどんな事ができるか?
と言うことの第二弾として、
「ページのスクロールに応じて」セクションごとに画像が、シャッターが開く様なエフェクトをともなって出現する例をもとに、記事を書きました。
今回の記事は、「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)