Webの動きを作るとき、最初に決めるのはライブラリ名ではありません。
何をきっかけに、どの状態を、どんな進み方で、どこへ描くのか。
ここが決まると、Native CSSで足りるのか、JavaScriptが必要なのか、GSAPやThree.jsを使うべきなのかを判断できます。
僕が知りたいのも、ライブラリの一覧ではありません。
- ブラウザの中で何が起きているのか
- その仕組みを最小コードでどう実装するのか
- 表現が大きくなったとき、何へ切り替えるのか
- その技術を選ぶ理由を自分で説明できるか
この記事は、Webの動きを仕組み → 実装手段 → 選択条件の順で整理した地図です。
Webの動きは6つの工程でできている
どのアニメーションも、まず次の6つへ分けます。
- 1. 入力クリック、スクロール、時間
- 2. 状態閉じる、開く、選ぶ
- 3. 進行度開始0から終了1まで
- 4. 補間途中の値を作る
- 5. 描画DOM、Canvas、3Dへ反映
- 6. 確認負荷、操作、動きの軽減
根本は、入力を0〜1の進行度へ変え、その途中の値を描画することです。ライブラリが変わっても、この流れは変わりません。
たとえば、カードが500msで右へ200px動く場合はこうなります。
click
→ closed から open へ
→ 0〜1を500msで進める
→ ease-outで途中の値を作る
→ translateへ反映する
スクロールに合わせて3Dカメラが進む場合も、構造は同じです。
scroll
→ セクションの開始位置と終了位置を決める
→ 現在位置を0〜1へ直す
→ 必要なら補間する
→ Three.jsのcamera.positionへ反映する

GSAPもThree.jsも、この6工程を消してくれるわけではありません。複雑になった工程を、書きやすく管理しやすくしてくれます。
実装手段は「進行度を誰が作るか」で選ぶ
動きの実装で迷ったら、時間を誰に進めてもらうかを考えます。
- 状態が変わるCSS Transition
- 決まった順番で進むKeyframes / WAAPI
- スクロールで進むScroll-driven / GSAP
- 指やマウスで進むPointer Events + rAF
二つの状態ならCSS。再生位置を操作するならJavaScript。スクロールやポインターが時間の代わりになる場合は、その入力を0〜1へ直します。
状態が変わるだけならCSS Transition
ホバー、開閉、選択、表示切り替えのように、開始と終了が2つの状態で表せるならCSSから始めます。
.card {
translate: 0 0;
transition: translate 240ms ease-out;
}
.card:hover {
translate: 0 -8px;
}
ここではブラウザが進行度を作ります。JavaScriptは不要です。
判断基準は簡単です。
- 状態が2つで表せる
- 途中を細かく制御しない
- 再生位置を外から操作しない
この3つなら、まずTransitionで十分です。
決まった順番を再生するならKeyframesかWeb Animations API
0%・40%・100%のように途中の状態が必要なら@keyframesを使います。
再生、停止、逆再生、現在位置の変更をJavaScriptから行いたいならWeb Animations APIへ進みます。
const animation = element.animate(
[
{ opacity: 0, translate: "0 16px" },
{ opacity: 1, translate: "0 0" }
],
{ duration: 400, easing: "ease-out", fill: "both" }
);
animation.pause();
animation.currentTime = 200;
見た目はCSSでも、操作権はJavaScriptに置けます。
スクロールは「入った瞬間」と「進み続ける」を分ける
要素が画面へ入ったときに一度だけ表示するならIntersectionObserverです。
スクロール量に合わせて0〜1を連続して使うなら、Scroll-driven Animationsか、スクロール位置を正規化する処理が必要です。
const start = section.offsetTop;
const end = start + section.offsetHeight - innerHeight;
const progress = Math.min(1, Math.max(0, (scrollY - start) / (end - start)));
大切なのはscrollYをそのまま使わないことです。表現が必要としている区間を0〜1へ直してから、座標や透明度へ渡します。
指やマウスへ追従させるならPointer EventsとrequestAnimationFrame
ドラッグ、視差、追従カーソルのように入力が毎回変わる表現はJavaScriptで進行度を作ります。
let targetX = 0;
let currentX = 0;
addEventListener("pointermove", (event) => {
targetX = event.clientX;
});
function frame() {
currentX += (targetX - currentX) * 0.12;
cursor.style.translate = `${currentX}px 0`;
requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
入力値と表示値を分け、毎フレーム少しずつ近づける。この考え方がlerpやspringの入口です。
DOM・SVG・Canvas・3Dは描きたい量で選ぶ
時間の進め方が決まったら、次は描画先です。
| 描画先 | 向いている表現 | 切り替える目安 |
|---|---|---|
| DOM + CSS | ボタン、カード、メニュー、記事UI | 意味のある要素が中心なら最初に選ぶ |
| SVG | ロゴ、線、図解、チャート、モーションパス | 形をDOMとして選択・操作したい |
| Canvas 2D | 粒子、波、描画ツール、大量の2D要素 | DOM要素を増やすより1枚へ描く方が自然 |
| WebGL / Three.js | カメラ、奥行き、光、立体、シェーダー | 3D空間そのものが体験の意味になる |
| WebGPU | 大量計算、独自レンダリング、GPU計算 | 既存の描画手段では計算量や設計が足りない |
DOMは意味とアクセシビリティを持ちやすい反面、大量の要素を毎フレーム動かす用途には向きません。
Canvasは大量描画に向きますが、描いた丸や文字はDOM要素ではありません。クリック判定や読み上げは別に設計します。
Three.jsは、scene、camera、geometry、material、light、rendererを使って3D空間を組み立てます。単に回転するカードを作るために導入するものではありません。

WebGPUはThree.jsの上位版ではありません。GPUへ描画や計算の命令を組み立てる、より低い層のAPIです。最初から選ぶのではなく、何を計算したいかが明確になってから検討します。
ライブラリは「難しい工程をどこへ任せるか」で選ぶ
僕はNative CSSとJavaScriptを基準にします。Nativeが偉いからではありません。仕組みとコードの距離が近く、問題が起きた場所を追いやすいからです。
そのうえで、複雑さが増えた工程だけをライブラリへ渡します。
- 時間の組み立てが複雑GSAP
- UI状態と動きを近づけたいMotion
- 大量の2D描画PixiJS
- カメラ・光・立体が必要Three.js
- スクロールの感触を変えたいLenis
- 独自のGPU計算が必要WebGPU
最初から全部を入れません。Nativeで作り、管理できなくなった工程だけ置き換えます。

GSAPを選ぶ条件
GSAPは、複数要素の開始位置、重なり、待ち時間、逆再生を1本のタイムラインとして管理したいときに使います。
const timeline = gsap.timeline();
timeline
.to(".title", { opacity: 1, y: 0 })
.to(".image", { scale: 1 }, "<0.15")
.to(".caption", { opacity: 1 }, "-=0.2");
CSSのdelayが増え、前の時間を直すたびに後ろも修正しているなら、GSAPへ移る理由があります。
ScrollTriggerは、スクロール区間、固定、進行度、複数シーンの同期をまとめたいときに使います。表示開始だけならIntersectionObserver、単純なスクロール進行ならNative CSSも候補です。
Motionを選ぶ条件
Motionは、UIの状態とアニメーションを近い場所で宣言したいときに向いています。
特にReactなどで、要素の追加・削除、レイアウト変更、gesture、springをコンポーネント単位で扱うときに選びやすいです。
複雑な映像的タイムラインを作るならGSAP。UIの状態変化を宣言的に扱うならMotion。この違いで考えます。
Three.jsを選ぶ条件
Three.jsは、カメラ、立体、光、素材が表現の中心にあるときに選びます。
DOM要素を3D風に傾けたいだけならCSSで足ります。3Dモデルの中を移動する、光で質感を変える、粒子を空間へ配置するならThree.jsが候補です。
PixiJSを選ぶ条件
大量のスプライト、2Dゲーム、画像フィルターのように、CanvasやGPUで2Dをまとめて描きたいときに使います。
DOMのカード一覧を速くするために選ぶものではありません。描画対象をCanvasの中へ移す設計が必要です。
Lenisを選ぶ条件
Lenisは、アニメーションライブラリではなく、スクロールの入力と表示位置の間へ滑らかさを加える道具です。
僕は標準スクロールを基本にします。サイト全体の体験として慣性が必要で、アンカー移動、キーボード、モーダル、prefers-reduced-motionまで確認できる場合だけ導入します。
「なんとなく高級に見える」だけでは採用理由にしません。
作りたい表現から実装を選ぶ
| 作りたいもの | 最初に使うもの | 切り替え条件 |
|---|---|---|
| ボタンやカードの反応 | CSS Transition | 途中状態や再生制御が必要ならWAAPI / Motion |
| 順番に現れるHero | CSS Keyframes | 要素数と時間調整が増えたらGSAP |
| スクロールで一度表示 | IntersectionObserver | 進行度と同期するならScroll-driven / GSAP |
| スクロール連動の長い演出 | Scroll-driven Animations | 固定・複数シーン・細かな同期が増えたらGSAP |
| 追従カーソルやドラッグ | Pointer Events + requestAnimationFrame | springやgesture管理が増えたらMotion |
| 大量の2D粒子 | Canvas 2D | スプライト・フィルター管理が増えたらPixiJS |
| カメラで進む3D空間 | Three.js | 独自GPU計算が主役ならWebGPUも検討 |
選ぶ前に、次の7問へ答えます。
- 入力は時間、クリック、スクロール、ポインターのどれか
- 状態はいくつあるか
- 0〜1の進行度を誰が作るか
- 描画先はDOM、SVG、Canvas、3Dのどれか
- 同時に動く対象はいくつか
- 途中で停止、逆再生、同期が必要か
- 動きを減らしても内容と操作が成立するか
答えられない項目があるなら、まだライブラリを決める段階ではありません。
4つの動きを触って理解する
説明だけでは、動きの仕組みはつかみにくいものです。下の4例は、入力が進行度になり、見た目へ変わるところを実際に試せます。すべてNative CSSとJavaScriptだけで動きます。
保存したサンプルは、ブラウザで開くだけで動きます。
1. 状態を切り替える
コードを見る
button.addEventListener("click", () => {
card.classList.toggle("is-open");
});
.box { transition: transform 360ms; }
.is-open .box { transform: translateY(0); }2. 順番に動かす
コードを見る
dots.forEach((dot, index) => {
dot.animate(keyframes, {
duration: 700,
delay: index * 140
});
});3. 進行度で動かす
コードを見る
const progress = range.value / 100;
stage.style.setProperty(
"--progress", progress
);
// スクロール量も同じ0〜1へ変換できる4. 少し遅れて追いかける
コードを見る
current += (target - current) * 0.14;
follower.style.left = current + "px";
requestAnimationFrame(update);
// 差を少しずつ埋める = 補間最初に作る3つで仕組みがつながる
学習はAPIの順番ではなく、同じ仕組みを少しずつ大きくします。
1. ホバーで持ち上がるカード
CSS Transitionで、状態、時間、easing、transformを理解します。
2. スクロール量で進むバー
スクロール区間を0〜1へ直し、入力と進行度を分けます。
3. マウスを少し遅れて追う円
Pointer Events、requestAnimationFrame、補間、描画をつなぎます。
この3つをNativeで作れれば、GSAPやMotionのコードを見たときも、何を任せているのかが分かります。
その次に、同じ進行度をSVGの線、Canvasの粒子、Three.jsのカメラへ渡します。描画先が変わっても、仕組みは変わりません。
技術名から選ばない。入力、進行度、描画先、規模から選ぶ。
これが、Webの動きを仕組みから実装へつなげる判断軸です。
読むならこの順番
全部を読む必要はありません。今作っている表現に必要な場所だけ開きます。
仕組みを理解するために読む
- W3C — Web Animations:時間、進行度、再生状態の共通モデルを確認する
- W3C — CSS Transitions:状態の変化からアニメーションが生まれる仕組みを確認する
- W3C — Scroll-driven Animations:時間の代わりにスクロール位置を使う考え方を確認する
- W3C — Pointer Events:マウス、指、ペンを同じ入力として扱う仕組みを確認する
仕様書は最初から最後まで読まず、記事で分からなかった言葉の定義を確かめる辞書として使います。
実装するときに読む
- 3D空間を作る:Three.js Manual — Fundamentals
- 複数の動きを時間軸へ並べる:GSAP Docs — Timeline
- スクロール区間と動きを同期する:GSAP Docs — ScrollTrigger
- UI状態とアニメーションを組み立てる:Motion Docs
- 大量の2D要素を描く:PixiJS Guides
- スクロールの感触を調整する:Lenis
読む順番も技術名ではなく、今困っている工程から決めます。







Nativeから始める方針は仕組みを理解しやすい一方、実案件では対応ブラウザ、保守する人、既存構成も判断材料になります。複雑さだけでなく、運用条件も含めて選ぶ必要があります。
CSS、JavaScript、GSAP、Motion、Three.jsを同じ判断軸で比べている点がこの記事の特徴です。図で仕組みをつかみ、操作例で結果を見てからコードへ進めます。
この記事では、技術名から選ばず、入力・状態・進行度・補間・描画・確認の順で考えられるように整理しました。まず4つの動きを触り、必要な工程だけ持ち帰ってください。