目次
情報確認日:2026年10月15日。GSAP 3系の公式資料を確認して作成した、本サイト独自の実装例です。
画面幅ごとの演出と、動きを減らす設定への配慮をgsap.matchMedia()で管理します。条件変更時のrevert、イベントの後片付け、CSSとの役割分担を説明します。
スポンサーリンク
幅の違いを、移動量だけで吸収しない
大きな画面で100px動くカードが、小さな画面でも同じ動きに向いているとは限りません。一方で、スマートフォンだから必ず全アニメーションを止める必要もありません。レイアウトはCSSで成立させ、演出に必要な値や有効条件をGSAP側で分けると、責任が明確になります。
matchMediaは、条件が一致したときの生成と、条件が変わったときの元へ戻す処理をまとめるために使います。window.innerWidthを初期化時に一度読むだけの構成と違い、表示後の幅変更も管理しやすくなります。CSSのメディアクエリーと、同じ境界値を共有することも大切です。
conditions構文は、どれか一つが一致すると動く
この例ではdesktop、mobile、reduceの三条件を指定しています。コールバックは、すべての条件が真になったときだけ実行されるのではありません。いずれかが一致すれば実行され、context.conditionsから、それぞれが一致しているか確認します。
desktopとmobileで通常の画面幅を分け、reduceはOSやブラウザーの設定を反映します。reduceが真なら早期returnし、CSSの通常状態を表示します。reduceだけを追加すればすべての配慮が済むのではなく、条件の中で何を作らないかを決める必要があります。
スポンサーリンク
条件が変わると、以前の生成を戻して作り直す
画面を広げたり狭めたりすると、以前のコールバック内で作成したGSAPの状態が戻され、新しい条件で生成されます。インラインのtransformが残ったまま、CSSだけが別のレイアウトへ変わる問題を減らせます。reduced motionへ切り替えたときも、元のCSSが読める状態なら自然に戻せます。
ただし、条件が変わるたびに再生が始まる構成には注意します。連続したresizeで毎回演出を見せたくない画面なら、初回表示の記録を別途持つ、そもそも幅ごとにTweenを作り直す必要があるか見直す、といった判断が必要です。このデモは挙動を学ぶため、条件変更後にも表示を再生します。
セレクターを対象コンポーネントへ閉じる
mm.addの第三引数にrootを渡し、コールバック内のセレクターが対象セクションに限定されるようにしています。同じクラスのカードを別の場所で使っていても、一つの設定からページ全体を意図せず動かしにくくなります。
ページに複数のfeatureを置くなら、rootを一つだけ取得するのではなく、それぞれを初期化する関数へ分けます。部品ごとにmmと破棄処理を保持すると、あとから一つだけ更新するときも扱いやすくなります。グローバルなセレクターを増やして対応し続けるより、部品の境界を先に作ります。
スポンサーリンク
addEventListenerは自分で外す
GSAPが作ったTweenを元へ戻すことと、ブラウザーへ登録したイベントを外すことは別です。サンプルはコールバックの戻り値として、removeEventListenerを行う関数を返しています。幅を何度も切り替えても、古いクリック処理が残らないようにするためです。
replayは既存のTweenをrestartするため、そのクリックのたび新しいTweenを生成していません。イベント内で毎回gsap.toを作る設計なら、その生成もContextへ記録する方法を検討します。後から呼ばれる関数が、自動で初期化時の記録範囲に含まれると決めつけないでください。
動きを減らすことと、表示をなくすことは違う
reduceの分岐ではカードを隠さず、静止状態をそのまま表示します。replayボタンを押しても動かないことが気になる場合は、利用者へ状態を説明する文言を付ける方法もあります。代わりに長い点滅を入れるなど、別の強い演出へ置き換える必要はありません。
大きな移動だけ減らして短いフェードは残すなど、プロダクトの方針によって調整できます。ただし、このサンプルは静止表示を選んでいます。見出し、説明、リンクの意味がアニメーションを見ないと分からない構成にはしないことを、先に確認しましょう。
確認は初期表示と変更後の両方で行う
広い画面で開始、小さな画面で開始、reduceで開始をそれぞれ確認します。さらに、表示したまま画面幅と設定を切り替え、スタイルの残りやイベントの多重登録がないか点検します。ページ遷移を繰り返すSPAでは、破棄時にmm.revert()が呼ばれることも確認します。
CSSとJavaScriptで境界値がずれていると、中間の幅だけ不自然になります。ブレークポイントを増やす前に、レイアウトと演出で同じ条件を使っているか確認してください。条件ごとの例外を重ねるより、基本状態を読みやすく作る方が、後の変更にも対応しやすくなります。
実装例:HTML・CSS・JavaScript
以下は独立したデモ用のコードです。既存のViteなど、npmパッケージを解決できる開発環境で npm install gsap を実行し、HTMLをbody内、CSSをスタイルシート、JavaScriptをmain.jsへ配置してください。main.jsはHTMLの末尾からtype="module"で読み込みます。WordPressの記事本文へそのまま実行用スクリプトを貼る例ではありません。
<section class="feature">
<h1>画面に合わせて、動きを変える。</h1>
<div class="feature-card">伝えたい内容は、いつでも読めます。</div>
<button type="button" id="replay">もう一度見る</button>
</section>
.feature { max-width:48rem; margin:4rem auto; padding:1.5rem; overflow:hidden; }
.feature-card { padding:3rem 1.5rem; margin:1rem 0; background:#9d95ff;
color:#0e100f; border-radius:1rem; }
@media(min-width:800px) { .feature-card { max-width:35rem; } }
import { gsap } from "gsap";
const root = document.querySelector(".feature");
const button = root.querySelector("#replay");
const mm = gsap.matchMedia();
mm.add({
desktop: "(min-width: 800px)",
mobile: "(max-width: 799px)",
reduce: "(prefers-reduced-motion: reduce)"
}, (context) => {
const { desktop, reduce } = context.conditions;
if (reduce) return;
const tween = gsap.from(".feature-card", {
x: desktop ? 100 : 20, opacity: 0, duration: 0.6, ease: "power2.out"
});
const replay = () => tween.restart();
button.addEventListener("click", replay);
return () => button.removeEventListener("click", replay);
}, root);
// このコンポーネントを破棄するときは mm.revert() を呼びます。
スポンサーリンク
サンプルを確認するときの条件
APIの使い方は公式資料と照合しています。掲載コードはGSAP 3.15.0とDOMを模した環境で読み込み・操作を確認しましたが、実ブラウザーでの見た目、タッチ操作、描画性能を保証するものではありません。採用前に対象ブラウザーと実機で確認してください。JavaScriptを無効にした状態でも、必要な内容と操作が残るかを確認します。



![JavaScriptモダンプログラミング完全ガイド [堅牢なコードを効率的に開発できる! ]](https://m.media-amazon.com/images/I/91NvEBSfCkL._SL1500_.jpg)