Appleのような極上のスクロール体験を!GSAP ScrollSmootherの導入から実践まで
Appleのウェブサイトを訪れて、スクロールしたときに「なんでこんなに滑らかなんだろう?」と感動したことはありませんか?
あの魔法のような感覚の正体は、慣性スクロール(Momentum-based scrolling / Inertia scroll) です。
本記事では、GSAP(GreenSock Animation Platform)の ScrollSmoother プラグインを使って、あの極上のスクロール体験を自分のプロジェクトで再現する方法を解説します。
朗報:GSAPが完全無料化されました!
2025年4月にWebflowがGreenSockを買収して以降、これまで有料ライセンス(Club GSAP)が必要だった ScrollSmoother を含む全プラグインが、商用利用も含めて100%無料 になりました。
導入のハードルはもうありません!
ScrollSmootherとは?
ScrollSmootherは、ブラウザのデフォルトのスクロール動作を拡張し、以下のような処理を行います。
- ブラウザのネイティブスクロールイベントを「監視」する
- 実際のレンダリング位置に対して、わずかな**イージング(遅延)**を適用する
結果: ユーザーの指(やマウスホイール)の動きよりもコンテンツが少し遅れて追従し、物理的な重みと高級感のあるスクロールが生まれます。
1. インストール
npmやyarnを使ってGSAP本体をインストールするだけで、すべての機能が手に入ります。Next.jsやReact環境でも同様です。
npm install gsap @gsap/react
React環境(Next.js含む)でGSAPを安全に使うために、公式の @gsap/react パッケージも一緒にインストールしておくことを強く推奨します。
HTMLコーディングで手軽に試したい場合は、CDNも利用可能です。
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12/dist/ScrollTrigger.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12/dist/ScrollSmoother.min.js"></script>
2. 必須となるHTML / CSS構造
ScrollSmootherを正しく動作させるには、ラッパーとなる2つの要素が必要です。
<body>
<div id="smooth-wrapper">
<div id="smooth-content">
<!-- ページ全体の内容(Header, Hero, Galleryなど)をここに配置します -->
<section class="hero">...</section>
<section class="portfolio-gallery">...</section>
</div>
</div>
</body>
| 要素 | 役割 |
|---|---|
#smooth-wrapper |
画面全体を覆う固定(fixed)のコンテナ |
#smooth-content |
実際に動く要素。GSAPがこの要素に transform: translateY() を適用してスクロールさせる |
#smooth-wrapper {
overflow: hidden;
position: fixed;
height: 100%;
width: 100%;
top: 0;
left: 0;
}
#smooth-content {
overflow: visible;
width: 100%;
}
3. 初期化(Next.js / Reactの例)
最近のフロントエンド開発で主流のNext.js(App Router)環境では、コンポーネントのアンマウント時のクリーンアップやStrict Mode対策が重要です。
公式の useGSAP フックを使うことで、これらを簡単にクリアできます。
"use client"; // Next.js App Routerの場合
import gsap from "gsap";
import ScrollTrigger from "gsap/ScrollTrigger";
import ScrollSmoother from "gsap/ScrollSmoother";
import { useGSAP } from "@gsap/react";
// プラグインの登録
gsap.registerPlugin(ScrollTrigger, ScrollSmoother);
export default function SmoothScrollLayout({ children }) {
useGSAP(() => {
ScrollSmoother.create({
wrapper: "#smooth-wrapper",
content: "#smooth-content",
smooth: 1.5, // スクロールの滑らかさ(秒数)。1.5〜2が自然です。
effects: true, // data-speed や data-lag を有効化(超重要!)
smoothTouch: 0.1, // タッチデバイスでの滑らかさ(0で無効化)
});
});
return (
<div id="smooth-wrapper">
<div id="smooth-content">
{children}
</div>
</div>
);
}
useGSAP の第2引数にdependencies arrayを渡さない場合、マウント時に1回だけ実行されます。ScrollSmootherの初期化はページ単位で行うため、基本的にこれで問題ありません。ただし、ルート変遷(ページ遷移)が発生する場合は、各ページコンポーネントで個別に初期化するか、router.pathname をdependenciesに含めてください。
React Strict Modeについて
Next.js App RouterはデフォルトでStrict Modeが有効です。useGSAP フックは内部でクリーンアップ処理を自動的に行うため、Strict Modeによる二重実行の問題を安全に回避できます。useEffect を使う場合は手動で ScrollSmoother.getById("smoother")?.kill() などのクリーンアップが必要になるため、useGSAP の使用を強く推奨します。
4. data属性だけで実装できるパララックスと遅延効果
effects: true を設定すると、JSを書かずにHTMLのdata属性だけでリッチな視差効果(パララックス)を実装できます。特に、写真メインのポートフォリオサイト等でグリッドレイアウトを組む際に非常に効果的です。
<!-- スクロールよりも遅く動く(背景画像などに最適) -->
<img src="high-res-photo.jpg" data-speed="0.5" style="will-change: transform;" />
<!-- スクロールよりも速く動く(手前に浮き出る要素) -->
<div class="floating-booking-card" data-speed="1.5"></div>
<!-- 物理的な「遅延」を生み出す(スクロール後、ゴムのように少し遅れて追いつく) -->
<div class="gallery-item" data-lag="0.5"></div>
| 値 | 動作 |
|---|---|
data-speed="1" |
通常のスクロール速度(デフォルト) |
data-speed="0.5" |
半分の速度(奥にあるように見える) |
data-speed="1.5" |
1.5倍の速度(手前に浮き出るように見える) |
data-lag="0.5" |
0.5秒遅れてゴムのように追いつく |
5. ScrollTriggerとの連携(Apple風ヒーローセクション)
ScrollSmootherはGSAPの ScrollTrigger と完全に統合されています。特定のセクションをピン留め(固定)しつつアニメーションさせるのも簡単です。
// 初期ロード時のフェードイン
gsap.from(".hero-text", {
opacity: 0,
y: 60,
duration: 1.2,
ease: "power3.out",
delay: 0.3,
});
// スクロールに合わせてテキストを拡大&フェードアウト
gsap.to(".hero-text h1", {
scrollTrigger: {
trigger: ".hero",
start: "top top",
end: "bottom top",
scrub: 1, // スクロール量にアニメーションをリンクさせる
},
scale: 1.2,
opacity: 0,
});
6. パフォーマンスを落とさないための重要ポイント
GPUアクセラレーションを活かす
ScrollSmootherは内部的に transform: translateY() を使用するため、リフロー(レイアウトの再計算)が発生せず高速です。高解像度の画像など、重い要素にはあらかじめCSSで will-change: transform; を付与しておくとブラウザのレンダリングがさらに最適化されます。
position: fixed の配置に注意
#smooth-content の内側に fixed 要素を置かないでください(コンテンツと一緒にスクロールされてしまいます)。固定ヘッダーなどは必ず #smooth-wrapper の外側に配置しましょう。
<body>
<!-- 固定ヘッダーはwrapperの外に置く -->
<header style="position: fixed; z-index: 100;">...</header>
<div id="smooth-wrapper">
<div id="smooth-content">
<!-- ここにfixed要素を置かない -->
...
</div>
</div>
</body>
モバイルでの最適化
スマホのネイティブスクロールは元々非常に滑らかです。モバイル環境では smoothTouch の値を 0 または非常に小さく保ち、不要な処理落ち(FPSの低下)を防ぐのがベストプラクティスです。
アクセシビリティ(prefers-reduced-motion)への対応
前庭障害(Vestibular disorder) などを持つユーザーにとって、過度なスクロールアニメーションは身体的な不快感を引き起こすことがあります。OSの「視差効果を減らす」設定を尊重するため、以下のコードを必ず追加しましょう。
const prefersReducedMotion = window.matchMedia(
"(prefers-reduced-motion: reduce)"
).matches;
if (!prefersReducedMotion) {
ScrollSmoother.create({
wrapper: "#smooth-wrapper",
content: "#smooth-content",
smooth: 1.5,
effects: true,
});
}
prefers-reduced-motion はWCAG 2.1のガイドラインでも推奨されているアクセシビリティ対応です。ScrollSmootherを使うすべてのプロジェクトで実装することをお勧めします。
7. よくあるエラーと対処法
ScrollSmoother is not defined
プラグインの登録が ScrollSmoother.create() より前に行われているか確認してください。
// 必ずcreate()の前に登録する
gsap.registerPlugin(ScrollTrigger, ScrollSmoother);
レイアウトが崩れる / コンテンツが見えない
#smooth-wrapper が overflow: hidden かつ position: fixed になっているか確認してください。height: 100% が効かない場合は height: 100svh を試してみてください。
Next.js で window is not defined エラー
ScrollSmootherはブラウザAPIに依存するため、サーバーサイドでは実行できません。useGSAP フック内に記述するか、typeof window !== "undefined" のチェックを追加してください。
useGSAP(() => {
if (typeof window === "undefined") return;
ScrollSmoother.create({ ... });
});
React Hydrationエラー
"use client" ディレクティブがファイルの先頭に記述されているか確認してください。ScrollSmootherを使うコンポーネントは必ずClient Componentである必要があります。
8. 他のライブラリとの比較
| ライブラリ | バンドルサイズ | パララックス組み込み | React相性 | メンテナンス状況 |
|---|---|---|---|---|
| GSAP ScrollSmoother | ~100KB(GSAP全体) | あり(data属性で簡単) | 公式フック対応 | 活発(Webflow傘下) |
| Lenis | ~4KB | なし(自前実装が必要) | 良好 | 活発 |
| Locomotive Scroll | ~20KB | あり | やや複雑 | 頻度低下気味 |
選び方のポイント:
- GSAPをすでに使っている → ScrollSmoother 一択。シームレスに統合できる。
- 軽量さ優先・パララックス不要 → Lenis が最適。
- 新規プロジェクトでGSAPを使わない → Lenis を検討する価値あり。
おわりに
GSAP全機能の無料化により、ScrollSmootherは間違いなくモダンWeb開発における最強の選択肢の1つになりました。
滑らかなスクロールは、単なる見た目の問題ではなく、ユーザーがサイト(プロダクト)に対して感じる「重厚感」や「品質」に直結します。初めてスクロールした瞬間に「おっ、このサイト違うな」と思わせることができれば、開発者としての勝利です。
まずは smooth: 1.5 を設定し、背景画像に data-speed を追加するところから始めてみてください。そして忘れずに prefers-reduced-motion の対応も!
Happy Coding!