【iOS】ScrollTriggerを使うと画面トップへのスクロールが発生してしまう【GSAP】

あまり情報が見当たらなかった不具合に遭遇したので覚書きです。

事象の詳細

事象はReactで構築中のサイトで発生。
PCブラウザ開発者ツールのレスポンシブモードでは発生せず、実機のiPhone(iOS17)でのみ確認できました。

  • フォームの入力項目にフォーカスを当てるとページトップへスクロールしてしまう
    →iPhoneのステータスバータップでページトップにジャンプする時と同じような挙動。
  • 事象が発生する条件は不明
    →普通に画面上からスクロールしてきてタップすると、半々くらいの確率で発生。
    一度ページ最下部までスクロールして戻ってタップすると再現する確率が7割程度。

検証した内容

  • inputのフォーカスやクリック時にスクロールを止めるJSを追加
    →解消されず(トップヘスクロール後にスクロール停止が有効化されてしまった)
  • 各ライブラリを順に除去して確認
    GSAPを読み込んでいる時のみ問題が発生することを確認
    →GSAPでも、インポートとメインビジュアルのアニメーションの記述だけだと問題発生せず。

複数の要素に同じアニメーションを当てるためのコードを記述していると発生するようでした。

▼該当コード例

.const torights = gsap.utils.toArray(".toright");
torights.forEach((elm) => {
    gsap.fromTo(elm, 
         { opacity: 0, x: -50 },
         {
            scrollTrigger: {
                trigger: elm,
                start: 'top bottom-=100',
                once: true,
            },
            x: 0,
            opacity: 1,
            duration: 1,
            ease: "power4.out",
         }
    );
});.

原因と対処法

ScrollTriggerとiOSで調べてみると、バグの報告が見つかりました。

GSAP ScrollTrigger is causing a scroll to top on iOS 16 Safari(日本語:GSAP ScrollTriggerがiOS 16のSafariでトップへのスクロールを引き起こす )

報告によると、NuxtサイトをiOS16で閲覧時、スクロールアニメーションが終了したときにページが自動的にトップにスクロールバックしてしまうという話。

このページの情報をざっくりまとめると、以下のような内容(見解)でした。

  • 今回の事象はNuxtは関係ない
  • ScrollTriggerとiOSに関する問題で、具体的には「cssのscroll-behavior:smoothをscrolltriggersのあるページに適用した場合、特定のシナリオでページが一番上にスクロールバックすることがある問題
  • ScrollTrigger と scroll-behavior: smooth プロパティを混在させるのはよろしくない
  • GSAPの修正版(3.11.2)がリリースされた(scroll-behavior が一時的に autoになる調整)が、まだ事象が確認されている
  • 以降、根本的な修正がされるまでの暫定的な対応に関する議論

最新報告は昨年末と新しめで、私のケースではGSAP3.12.4、iOS17で発生していることを確認しているため、現役で起き得るバグなようですね。

上記の通り「scroll-behavior: smooth」プロパティを削除したところ、トップへのスクロール現象は無事解消しました。

まとめ

まとめ
  • ScrollTrigger を使用するページで使うCSSから「scroll-behavior: smooth プロパティ」を削除することで解消する
  • scroll-behavior: smooth プロパティを削除できない事情がある場合、GSAPもしくはiOSにて根本的な修正バージョンが出るまで暫定的な対処を試みる(前述バグ報告ページにいくつか対応案が記載されている)

ちなみに「scroll-behavior: smooth」はJS無しでスムーススクロールを実装してくれるもの。
原因を知ってから調べてみると、GSAPのScrollTriggerはiOSの慣性スクロールの相性があまりよくなさそうな話(iOS閲覧時で挙動がおかしい、パフォーマンスが落ちる)があるようです。

このプロパティは新しめのリセットCSSには含まれていることがあり、今回も最近使い始めたCSSの中にあったことで問題が発生していました。
心当たりがない場合は、一度使用しているリセットCSSを見てみるといいかもしれません。