GSAP ScrollTriggerで記事を「最後まで読ませる」。視線誘導の実装ガイド

はじめに

長文ページの演出は、派手さよりも「どこを読んでいるか分かること」が大切です。見出しが切り替わるタイミングや、次に読むべき要素が視覚的に伝わるだけで、ページの体験はかなり変わります。

この記事では GSAP と ScrollTrigger を使って、記事ページ向けのスクロール演出を実装します。まずは最小構成で入場演出を作り、次に進捗バーと固定ナビを組み合わせる運用寄りの構成まで広げます。

機能やライブラリの概要

GSAP はアニメーション記述を担当し、ScrollTrigger はスクロール位置とアニメーションの同期を担当します。組み合わせることで、表示タイミング・進捗・固定表示を一貫した設計で扱えます。

記事ページで使うときは、次の3つを先に決めると破綻しにくくなります。

  • どの要素をいつ表示させるか
  • 戻りスクロール時にどう見せるか
  • ヘッダー高さをどこで吸収するか

インストール方法

JavaScript

PowerShell
npm i gsap

JavaScript

JavaScript
import { gsap } from "gsap"
import { ScrollTrigger } from "gsap/ScrollTrigger"

gsap.registerPlugin(ScrollTrigger)

基本の使い方

最初は、章ブロックがビューポートに入ったときに自然に表示する最小例です。開始位置を固定しておくと、ページの内容が増えても挙動がぶれにくくなります。

HTML

HTML
<article class="post">
  <section class="js-section">導入</section>
  <section class="js-section">比較</section>
  <section class="js-section">実装</section>
</article>

CSS

CSS
.post {
  display: grid;
  gap: 56px;
}

.js-section {
  opacity: 0;
  transform: translateY(20px);
}

JavaScript

JavaScript
const sections = gsap.utils.toArray(".js-section")

sections.forEach((section) => {
  gsap.to(section, {
    opacity: 1,
    y: 0,
    duration: 0.55,
    ease: "power2.out",
    scrollTrigger: {
      trigger: section,
      start: "top 78%",
      toggleActions: "play none none reverse"
    }
  })
})

この構成は、技術記事、採用ストーリー、事例ページのように「順番に読ませたい」コンテンツで効果が出やすいです。演出が強すぎないため、UIの主役をテキストのまま保てます。

また、セクション単位でトリガーを分離しているので、後から章を追加しても修正範囲が小さく済みます。運用更新が多いメディア案件と相性が良いです。

応用コード

次は、記事進捗バーと目次ナビの固定表示を追加します。構造が増えるので、HTML/CSS/JavaScript をまとめて載せます。

HTML

HTML
<header class="reading-ui">
  <div class="reading-ui__progress" id="js-progress"></div>
  <nav class="reading-ui__toc" id="js-toc">目次</nav>
</header>
<article class="post" id="js-post">...</article>

CSS

CSS
.reading-ui {
  position: sticky;
  top: 0;
  z-index: 10;
  background: rgb(255 255 255 / 88%);
  backdrop-filter: blur(8px);
}

.reading-ui__progress {
  height: 3px;
  transform-origin: left center;
  transform: scaleX(0);
  background: #0ea5e9;
}

JavaScript

JavaScript
const post = document.getElementById("js-post")
const progress = document.getElementById("js-progress")
const toc = document.getElementById("js-toc")

ScrollTrigger.create({
  trigger: post,
  start: "top top",
  end: "bottom bottom",
  onUpdate: (self) => {
    gsap.set(progress, { scaleX: self.progress })
  }
})

ScrollTrigger.create({
  trigger: post,
  start: "top top+=80",
  end: "bottom top+=80",
  onEnter: () => toc.classList.add("is-fixed"),
  onLeaveBack: () => toc.classList.remove("is-fixed")
})

注意点

ScrollTrigger を複数重ねると、開始位置のずれが見えやすくなります。固定ヘッダーがある場合は startend を必ずヘッダー高さ込みで調整するのが安全です。

さらに、prefers-reduced-motion への配慮は初期段階で入れておくと後戻りを防げます。演出を無効化する分岐を先に用意しておくと、アクセシビリティ対応が楽になります。

まとめ

GSAP ScrollTrigger は、記事ページの読了体験を整える用途で非常に使いやすいです。入場演出、進捗、固定ナビを段階的に追加する設計にすると、見た目と保守性を両立しやすくなります。

まずは最小構成で導入し、ユーザー行動を見ながら演出を足していく進め方がおすすめです。

ポイント

  • 派手さより読み順の補助を優先すると失敗しにくい
  • 章ごとのトリガー分離で運用時の変更に強くなる
  • 固定ヘッダーと reduced motion の考慮を先に入れる

参考リンク

read next