【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で調べてみると、バグの報告が見つかりました。
報告によると、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を見てみるといいかもしれません。