scroll-effects について
ウェブページに軽量なスクロール演出を加えるデザインスキル集です。作例ギャラリーに加え、外部ライブラリーを使えないプロジェクト向けの7つの標準JavaScriptパターンを収録し、動きを抑える設定と検証方法も扱います。
主な機能
- 01スクロール演出の作例ギャラリー
- 027種類の標準JavaScriptパターン
- 03表示演出と段階的なテキスト表示
- 04ナビゲーション縮小と目次連動
- 05パララックスとトップへ戻る機能
活用シーン
- 01ランディングページに表示演出と段階表示を追加
- 02ドキュメントに目次連動とトップへ戻る機能を追加
- 03外部ライブラリーなしでスクロール演出を実装
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ rheinmir/ setup --skill scroll-effectsインストール後、Claude Code で/scroll-effectsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
assets/demo.htmlscroll-effects.cssscroll-effects.js詳細
スキル:scroll-effects
ページスクロールエフェクトのハブ:Rheinmir/uiux-asset に収録されたオリジナル版64点(freefrontend/CodePen、MIT)を、ギャラリーで確認してファイルをそのままコピーできます。外部ライブラリを取り込めないプロジェクト向けに、assets/ に自作のバニラ実装エフェクトを7点用意しています。
WHAT
目的とコンテキスト
- 目的: ランディングページに軽量なページスクロールエフェクトを追加します。デフォルトでは、
Rheinmir/uiux-assetのオリジナル版ファイルをそのままコピーします。外部ライブラリを取り込めないプロジェクトでは、assets/のバニラパターン7点を使用します。 - 使用するタイミング:
- スクロール時のフェードイン、文字のスタガー表示、視線を誘導するハイライト、縮小するナビゲーション、ページ上部へ戻るボタン、セクションに追従する目次、または軽いパララックスが必要なページ。
- ユーザーが「スクロールエフェクト」「scroll to top」「scrollspy」「parallax」「スクロール時のリビール」と言った場合。
- 対象外: 次の用途には使用しないでください。GPU負荷の高いシネマティックな画像トランジション(
blurを使用)、タイムラインのマイルストーン(timelineを使用)、GSAP ScrollTrigger のような複雑な水平スクロールのピン留めセクション(この軽量スキルの対象外であることをユーザーに明示してください)。
メンタルモデル
必要なエフェクト → オリジナル版64点のギャラリー(デフォルト。ファイルをそのままコピー)またはバニラパターン7点(ライブラリを取り込めない場合) → design.md に合わせてトークンを調整 → IntersectionObserverを1つ、rAF付きスクロールリスナーを1つ → reduced-motionですべて無効化 → playwrightで検証。ギャラリーの項目が子スキルに該当する場合は、該当する子スキルに引き継ぎます。
入力と出力の契約
| フィールド | 必須? | 意味 | |
|---|---|---|---|
| In | 必要なエフェクト | はい | 7つのパターンのいずれか、またはギャラリーの項目 |
| In | プロジェクトの制約 | いいえ | 外部ライブラリ/ファイルを取り込めるか、design.md があるか |
| Out | プロジェクト内のエフェクトファイル | はい | そのままコピーしたオリジナル版(先頭行のクレジットコメントを保持)または調整済みのバニラアセット |
| Out | 検証の証拠 | はい | スクロール前後のスクリーンショット、.is-in の出現、水平オーバーフローがないこと |
ルールと機能
- RULE-01 (MUST):
prefers-reduced-motion: reduceの場合はすべて無効化します。CSSで.is-inをトランジションなしですぐに表示し、JSではスムーズスクロールとパララックスを無効にします(アセットには実装済みです。調整時にこの分岐を削除しないでください)。 - RULE-02 (MUST):リビール、スタガー、ハイライト、TOCで
IntersectionObserverを1つだけ共有します(scroll-effects.jsに統合済みです)。Observerを4つ個別に作らないでください。 - RULE-03 (MUST):スクロールリスナーは1つだけにし、rAFでスロットリングします。ナビゲーション、トップへ戻る機能、パララックスが各フレームで共通の
scrollYを読み取るようにし、scrollリスナーを3つ別々に登録しないでください。 - RULE-04 (MUST):
playwright-verifyで検証します。スクロール前後のスクリーンショットを撮影し、.is-inの出現をアサートし、パララックスによるオーバーフローがないことを測定します。 - RULE-05 (MUST):
design.mdがあるプロジェクトに適用する場合は、色/スペーシングのトークンを変更し、data-se-*の名前は維持します(JSがこれらを参照します)。 - 機能:ギャラリー/外部リポジトリのアセット(ネットワーク経由)または内部アセットの読み込み、プロジェクトのフロントエンドファイルの作成、ローカルHTTP経由でのヘッドレスブラウザー実行。
失敗の境界
- 要求が高負荷なWebGL、タイムラインのマイルストーン、または複雑なGSAPのピン留めセクションの場合は、対象外として blocked にします。対象外であることをユーザーに明示し、適切なスキルを案内してください。
- 外部ギャラリー/リポジトリにアクセスできない場合、またはプロジェクトで外部ライブラリが禁止されている場合は、バニラパターン7点を使用します(エラーではありません)。
- playwrightの検証で
.is-inが見つからない場合、または水平オーバーフローがある場合は、failed とし、修正してから再検証します。
HOW
メインワークフロー
| Step | Type | Inputs | Action | Outputs/exit | Failure/next |
|---|---|---|---|---|---|
| W01 | judgment | 要求 | 対象範囲に合致するか確認します(blur/timeline/GSAPのピン留めではないこと) | 対象範囲内のエフェクト | 対象外 → blocked |
| W02 | judgment | プロジェクトの制約 | 使用元を選択します。ギャラリーのオリジナル版(デフォルト)またはバニラの assets/(B01) | 使用元 | — |
| W03 | effect | 使用元 | オリジナル版:実行リンクを開く → .html(および _assets/)をそのままコピー → クレジットコメントを保持 → コンテンツ/画像/色のみを変更 | プロジェクト内のファイル | — |
| W04 | effect | design.md | 色/スペーシングのトークンを調整し、data-se-* と reduced-motion の分岐を維持 | 調整済みファイル | — |
| W05 | deterministic | HTTP経由のページ | playwright-verify:スクロール前後のスクリーンショットを撮影し、.is-in をアサートして、オーバーフローを測定 | PASS | FAIL → 修正してW05を繰り返す |
各ステップの詳細(W01〜W05の正規情報源):
オリジナル — まずはこちらを使用(ファイルをそのままコピーし、書き直さないでください)
作者のオリジナルコード(公開されているCodePen=MIT)は、外部リポジトリ Rheinmir/uiux-asset にあります — 実際に動作するギャラリー:https://rheinmir.github.io/uiux-asset/scroll-effects/ 。
手順:実行中のリンクを開いて実際のエフェクトを確認 → .html ファイル全体(ファイルから参照されている場合は _assets/ フォルダーも)をプロジェクトにコピー → 先頭行のクレジットコメントを残す → 内容/画像/色だけを変更します。ローカルでは HTTP 経由で実行し、file:// は使用しないでください。
オフライン用に一式が必要な場合は、git clone --depth 1 https://github.com/Rheinmir/uiux-asset を実行してください。
ハブ:ギャラリーの64項目すべてを閲覧し(名前/手法/作者で絞り込み)、該当する子スキルに進みます。
このスキルの assets/ は、自作した簡易版の vanilla 実装です — プロジェクトで外部ライブラリを読み込めない場合にのみ使用してください。通常は上記のオリジナルを使用します。
Assets
assets/demo.html(7項目すべてを組み合わせたデモページ)+ assets/scroll-effects.css + assets/scroll-effects.js — 読んでから ADAPT してください(プロジェクトに design.md があれば、それに合わせてクラス/トークンを変更してください)。
Branches
| ID | 種類 | 条件 | 動作 | スキップ/失敗 | 合流先 |
|---|---|---|---|---|---|
| B01 | conditional_required | プロジェクトで外部ライブラリ/ファイルを読み込めない | assets/ の vanilla パターン7種(下記の Reference 項目)をオリジナルの代わりに使用 | 外部ライブラリを読み込める → オリジナルのギャラリー | W04 |
| B02 | user_optional | オリジナル一式をオフラインで必要とする | Rheinmir/uiux-asset リポジトリを git clone --depth 1 で取得 | — | W03 |
| B03 | conditional_required | ギャラリー項目が子スキルに属する | 該当する子スキルに進む | — | 子スキルで終了 |
Validation と停止条件
ローカル HTTP 経由で実行します(file:// は使用しません)。Playwright でスクロール前後を撮影し、.is-in が確認でき、横方向のオーバーフローがなく、reduced-motion ではすべての要素がすぐに表示されれば PASS です。PASS したら停止します。FAIL の場合は修正して再検証します。
Examples
- 成功例: 「ドキュメントページに scroll to top と scrollspy を追加して。ライブラリは読み込めません」→ B01 で
assets/の[data-se-top]+[data-se-toc]を使用し、design.mdに合わせてトークンを変更してdata-se-*は維持 → Playwright で検証:scrollY > innerHeightでボタンが表示され、TOC のリンクに.is-activeが付与されます。 - 範囲外/失敗例: 「GSAP のようにピン留めされる横スクロールセクションを作って」→ この軽量スキルの範囲外です → ユーザーにその旨を明確に伝え、parallax の
data-se-parallaxで無理に実装しないでください。
Reference — 7つのパターン(最小限のマークアップ+仕組み)
1. スクロール時に表示 — [data-se-reveal]
要素を薄くし、少しスライドさせて、ビューポートに入ったときに表示します。
<div data-se-reveal>Lộ dần khi cuộn tới</div>
IntersectionObserver が .is-in を付与 → CSS の opacity/translateY トランジション。ギャラリーの scroll-effects #9(Animated Scroll Highlight Annotations)は用途の参考にしてください。コードは使用しないでください。
2. テキストを段階的に表示 — [data-se-stagger]
テキスト行を順番に表示します。
<h2 data-se-stagger>
<span>Dòng một</span><span>Dòng hai</span><span>Dòng ba</span>
</h2>
JS が各 span に --i を設定 → CSS の transition-delay: calc(var(--i) * 90ms)。既存の子要素ごとに分割し、テキストノードを独自に分割しないでください(DOM をシンプルに保ち、a11y の問題を防ぎます)。
3. スクロール時に強調表示 — [data-se-highlight] > mark
重要なポイントにマークを付け、段落がビューポートに入ると色の帯が左から右へ広がります。
<p data-se-highlight>Đọc tới đây <mark>ý chính hiện ra</mark> rồi đọc tiếp.</p>
mark は、親に .is-in が付いたときに background-size: 0% → 100% のトランジションを使用します。偽の span ではなく、意味的に正しい <mark> を使用してください。
4. スクロール時に縮む sticky ナビゲーション — [data-se-nav]
下にスクロールするとヘッダーが縮み、先頭に戻ると元の大きさになります。
<header data-se-nav class="site-nav">…</header>
スクロールリスナー(rAF でスロットル)で、scrollY > 24 のとき .is-shrunk を切り替えます。クラスを使って padding/font-size だけを変更し、フレームごとに inline style を設定しないでください。
5. ページ上部へ戻る — [data-se-top]
1画面分スクロールした後にだけ表示される、ページ上部へ戻るボタンです。
<button data-se-top aria-label="Về đầu trang">↑</button>
クリック時に window.scrollTo({ top: 0, behavior: "smooth" }) を実行します(prefers-reduced-motion の場合は "auto")。表示しきい値:scrollY > innerHeight。
6. Scrollspy TOC — [data-se-toc] a[href^="#"] + section[id]
sticky 目次で、閲覧中のセクションに対応するリンクを強調表示します。
<nav data-se-toc><a href="#s1">Mục 1</a><a href="#s2">Mục 2</a></nav>
<section id="s1">…</section><section id="s2">…</section>
rootMargin: "-40% 0px -55% 0px" の IntersectionObserver を使用 → 一致するリンクに .is-active を付与します。ギャラリー #19(Auto-Generated Anchor TOC)はアイデアの参考にしてください。コードは自作します。
7. Parallax nhẹ — [data-se-parallax="0.2"]
Lớp nội dung trôi chậm hơn/nhanh hơn tốc độ cuộn.
<div data-se-parallax="0.15">Trôi chậm tạo chiều sâu</div>
rAF loop: translateY = (elCenter - viewportCenter) * speed. Giá trị speed khuyến nghị |v| ≤ 0.3; vượt quá gây say chuyển động. KHÔNG dùng cho chữ nhỏ cần đọc chính xác.
Origin
- User chốt "làm đi hỏi nhiều quá" → thay vì bulk-copy 81 tác phẩm, viết BỘ GỐC 7 pattern generic (kỹ thuật chuẩn ngành: IntersectionObserver/scroll listener/rAF — không phải biểu đạt sáng tạo riêng của ai) để downstream tham khảo code mẫu ngay, đúng cách
blur/timelineđã làm.