JavaScript

GSAPで、縦スクロールで横に動く(横スクロール)アニメーションをパララックス(慣性付)で

操作としては縦にスクロールさせているのに、動作としては横に動くようにする方法をご紹介します。GSAPというライブラリを用いた方法です。

部分的にそのような演出を施すと、サイトにメリハリがつけられます。

GSAPとは?

GSAPはウェブサイトに趣向を凝らしたアニメーションを実装することができるJavaScriptのライブラリです。

GSAPが用意しているものには、CSSのアニメーションプロパティで実現できることも多いのですが、縦にスクロールさせているのに横に動作するというアニメーションを実装する際にはGSAPのライブラリの一つである「ScrollTrigger」が便利です。ページスクロールをトリガーとして、設定したタイミングで指定のアニメーションが実行できます。

ここでは、GSAPのライブラリ「ScrollTrigger」を使った横スクロールアニメーションの実装方法をご紹介します。

縦スクロールで横に動かす実装内容のデモ

次のように、縦スクロールしてある地点に到達すると、その地点で縦スクロールが止まり、縦スクロールの動作に応じて一定の距離横スクロールするという実装をする方法をご紹介します。

See the Pen Untitled by Takahiro Inada (@tkhr1) on CodePen.

GSAPの利用方法

まずはGSAPを利用する方法です。

CDNを利用する場合

CDNを利用する場合は次の2つを読み込みます。
1つ目が基本的なプログラムで、2つ目はここでご紹介する横スクロールアニメーションを実装するために必要なプログラムです。

<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.3/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.3/ScrollTrigger.min.js"></script>

最新バージョンはこちらで確認してください。

npmの場合

コマンド

npm i gsap

JavaScript

import gsap from 'gsap';

ダウンロードして読み込む場合

次のページからダウンロードします。
GSAP Installation

ダウンロードしたファイルから以下2つのファイルを読み込みます。CDNのところで説明したのと同じで、1つ目が基本的なプログラムで、2つ目はここでご紹介する横スクロールアニメーションを実装するために必要なプログラムです。

<script src="./umd/gsap.js"></script>
<script src="./umd/ScrollTrigger.js"></script>

縦スクロールで横に動かす実装のコード

次にコードです。

HTML

<div class="box-01">
  <p>↓スクロールしてください。</p>  
</div>
<div class="box-02">
    <div class="slides-wrapper">
       <div class="slide"><img class="slide-img" src="画像ファイルの場所" alt=""></div>
       <div class="slide"><img class="slide-img" src="画像ファイルの場所" alt=""></div>
       <div class="slide"><img class="slide-img" src="画像ファイルの場所" alt=""></div>
       <div class="slide"><img class="slide-img" src="画像ファイルの場所" alt=""></div>
       <div class="slide"><img class="slide-img" src="画像ファイルの場所" alt=""></div>
    </div>
</div>
<div class="box-03"></div>

横スクロールさせる要素の外枠は2つの要素(ここで言う.box-02.slides-wrapper)で囲います。

CSS

.box-01,
.box-03{
  width: 100%;
  height: 100vh;
  background-color: #333;
  color: #fff;
  display: flex;
  justify-content: center;
  align-items: center;
}
.box-02{
   width: 100%;
   height: 100vh;
   display: flex;
   justify-content: center;
   align-items: center;
}
.slides-wrapper{
   display: flex;
   gap: 30px;
   width: calc(100% - 50px);
   margin: 0 auto;
   overflow: hidden;
}
.slide-img{
  width: 50vw;
  height: 50vh;
  object-fit: cover;
}

横スクロールさせる要素の高さはそれらしく動かすうえで条件があるので、色々試してみてください。理由としては、次のJavaScriptのところで説明するdiv.pin-spacerがHTMLに足されるというところにありますので、そのことを把握したうえで試すと、理屈が分かってくると思います。

JavaScript

const container = document.querySelector('.box-02');
const slides = document.querySelectorAll('.slide');
const containerWidth = container.offsetWidth;
gsap.to( slides, { // slidesに対して以下のアニメーションを設定
   xPercent: -110 * (slides.length - 1), // 横に動く方向と距離(この例は右側にスライドの合計幅より少し横スクロール)
   ease: "none", //アニメーションの種類をnoneにする
   scrollTrigger: {
      trigger: container, //containerに到達したら発火
      pin: true, // ピン留をtrueにすることでcontainerの縦スクロールが止まる
      scrub: 1, //スクロール当たりのアニメーションが動く時間
      end: () =&gt; "+=" + containerWidth, // 横スクロールが終わる地点
      anticipatePin: 1, // ピン留のタイミング
      invalidateOnRefresh: true, // リサイズ時の調整でtrueにしておく
  }
})
  • gsap.to()メソッドは、gsap( 第一引数, 第二引数 )とすることで第一引数を対象として、第二引数で指定した内容でアニメーションを実行します。
    ここの例で言うと、第一引数がdocument.querySelectorAll('.slide')で取得された変数slidesで、そのslidesに対して{}内のgsapのプロパティで指定したアニメーションが動くということです。
  • triggerはgsapが発火する地点を決めます。なお、startでそのエリア内の発火を座標で指定することができますが、この例のように省略した場合はデフォルト値であるstart: 'top top'、つまり対象エリア内の左上となります。
  • pintrueにすることで、triggerで指定したエリア(ここで言うcontainer)内の縦スクロールの動きを止めることができます。
    また、pintureにすることで、triggerで指定したエリアの外側にはdiv.pin-spacerが追加されます。div.pin-spacerにはGSAPにより自動で付けられるCSSがありますので、その値を確認すると理屈の理解が進むと思います。
  • scrubはスクロール当たりのアニメーションが動く時間を決めるもので、0.3~0.5だと普通の動きになり、1にすることで慣性のある動きになります。
  • anticipatePinは、ピン留の遅延を防ぐための調整で、基本的には1が推奨です。もし1で遅延する場合は少し値を変えてみるなどするようなものです。
  • invalidateOnRefreshは、リサイズによりスクロール値が再計算される場合に、内部で記録されている値をリセットさせることで正しくアニメーションが動くようにするものです。trueにしておきます。

横スクロールアニメーションのメリット

冒頭でも述べましたが、通常、縦スクロールするはずの操作で横スクロールすると、不思議な感覚になります。つまり特別な感覚をユーザーに与えることができて、他のサイトとの差別化に繋がると言えます。

他に横スクロールさせるUIとしてカルーセルスライダーがありますが、そちらは自動またはドラッグ/スワイプの操作で横に動かすというものになります。カルーセルスライダーは直感的で心地よい操作を提供するメリットがありますが、不思議な感覚というのはないのと、ユーザーが横スクロールさせずにそのまま縦スクロールさせてしまい、見てもらえない可能性が高いというデメリットがあります。

一方で本記事でご紹介したUIの場合、縦スクロールしたつもりが横に流れるので、カルーセルスライダーに比べて見てもらいやすいというメリットがあります。

横スクロールアニメーションのデメリット

本UIのデメリットとしては、操作が直感的ではないということ、必ずしも見たい部分ではない場合にも、下部に表示されている部分を飛ばしてみるということができず、ユーザーは横スクロールが終わるまでスクロールし続けなくてはいけないということがあります。

そのため、ユーザーが何度か訪れることが想定されるようなページで上部に配置してしまうと煩わしく感じられてしまうので、そうならないように留意することが望ましいと言えます。

CSSだけで横スクロールアニメーションの実装をする方法「Scroll-driven Animations」について

2023年7月にアップデートされたChrome115以降では、Scroll-driven Animationsという仕様がサポートされ、スクロールに連動したアニメーションがCSSだけで実装できるようになりました。

まだSafariがサポートしてないので、実案件では用いることが現実的ではない状況ですが、こちらの記事で詳しく解説していますので、よろしければご参照ください。

CSSだけでスクロールアニメーション!Scroll-driven Animations、animation-timelineプロパティを解説

なお、Scroll-driven Animationsの仕様は次のページで、まだ草案(draft)の状態です。

Scroll-driven Animations |W3C Working Draft, 6 June 2023

まとめ

GSAPはこのように、縦スクロールをピン留して横スクロールさせるという演出を施すのに便利なライブラリです。ぜひお試しください。

著者のイメージ画像

株式会社BringFlower
稲田 高洋(Takahiro Inada)

2003年から大手総合電機メーカーでUXデザインプロセスの研究、実践。UXデザイン専門家の育成プログラム開発。SEOにおいても重要なW3Cが定めるWeb標準仕様策定にウェブアクセシビリティの専門家として関わる。2010~2018年に人間中心設計専門家を保有、数年間ウェブアクセシビリティ基盤委員も務める。その後、不動産会社向けにSaaSを提供する企業の事業開発部で複数サービスを企画、ローンチ。CMSを提供し1000以上のサイトを分析。顧客サポート、サイト運営にも関わる。
2022年3月に独立後、2024年4月に株式会社BringFlowerを設立。SEOコンサルを活動の軸に据えつつ、AIライティングツールの開発と運営を自ら行う。グッドデザイン賞4件、ドイツユニバーサルデザイン賞2件、米国IDEA賞1件の受賞歴あり。