scroll-scrubbed-word-reveal について
スクロールに合わせて単語を表示しながら、元のテキスト、インラインの意味構造、アクセシビリティを保つウェブアニメーションスキルです。DOM の分割、進捗の対応付け、動きを減らす設定、後処理と検証を扱います。
主な機能
- 01アクセシブルな元テキストの保持
- 02テキストノード走査による単語分割
- 03スクロール進捗に応じた単語表示
- 04GSAP ScrollTrigger またはネイティブスクロール
- 05動きを減らす設定と後処理への対応
活用シーン
- 01記事の段落にスクロール表示を追加
- 02リンクや強調を保ったテキストアニメーション
- 03レスポンシブ、支援技術、逆スクロールの検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mengto/ skills --skill scroll-scrubbed-word-revealインストール後、Claude Code で/scroll-scrubbed-word-revealを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
REFERENCES.mdagents/openai.yamldemo/index.htmlPROMPT.md詳細
スクロールに連動した単語の表示
実際のテキストを置き換えたり、インラインのマークアップを壊したり、固定の行数に依存したりせずに、読み進み具合を表示します。
テキストを準備する
- アクセシビリティに対応した、変更されていないテキストソースを DOM 内に 1 つ残します。
TreeWalkerでテキストノードをたどります。コンテナーをtextContentやinnerHTMLで平坦化しないでください。script、style、フォームコントロール、および[data-no-split]が指定された要素はスキップします。- 空白以外のトークンのみを span に置き換え、空白ノードはそのまま正確に保持します。
- 分割されていない同等のアクセシブルなコピーを利用できる場合に限り、生成した span に
aria-hidden="true"を指定します。
推奨する構造:
<p class="reveal" data-reveal>
Motion should <em>explain</em> the next state, not decorate it.
</p>
行単位で分割しないでください。ブラウザーの行折り返しは、コンテナーの幅、言語、ズーム、フォントの読み込み状況に応じて変化できる必要があります。
スクロール位置を単語に対応付ける
セクションの進行度を唯一の基準として使用します。
const reveal = Math.min(1, Math.max(0, progress));
const local = Math.min(1, Math.max(0, reveal * wordCount - index));
word.style.setProperty("--word-progress", local);
--word-progress から、非表示状態の不透明度、ぼかし、垂直方向のオフセットを補間します。表示状態は通常のタイポグラフィと同一にしてください。
開始位置、終了位置、更新、または共有タイムラインを正確に制御する必要がある場合は、scrub を使って GSAP ScrollTrigger を使用します。単独のセクションには、依存関係のないスクロール位置の計測と requestAnimationFrame を使用します。
使いやすいデフォルト値を設定する
- 非表示時の不透明度:
0.12–0.3 - ぼかし:
4–10px - 垂直方向のオフセット:
0.08–0.22em - 表示にかけるスクロール範囲:段落の場合、ビューポートの
120–220% - 直接単語を重ねる割合:
10–30% - イージング:スクロール位置のマッピングには使用せず、必要な場合に限り視覚的な補間に使用します
値は CSS カスタムプロパティとして公開します。どの文章にも同じ再生時間を当てはめるのではなく、テキストの長さに応じてスクロール範囲を調整します。
強調表現を保持する
- リンク、
strong、em、マーク、アクセント用の span は、それぞれの意味とスタイルを保持します。 - デフォルトでは継承された色を使用します。トークンのインデックスではなく、元の要素にアクセントのスタイルを適用します。
- 必須のリンクを、ホバー時や読者が通過した後にしか表示しないでください。
- 元のテキストが変更された場合にのみ再分割します。レスポンシブな折り返しに合わせてトークンを再構築する必要はありません。
- クリーンアップ時に元の DOM を復元できるだけの状態を保持します。
読みやすさを保つ
- 実際の文書フローを使用します。コピーと根拠から短い意図的な読書時間が妥当と判断できる場合に限り、ピン留めします。
- 明示的に求められていない限り、タイプライターカーソル、ランダムな遅延、自動再生を使用しないでください。
prefers-reduced-motion: reduceの場合は、すべての単語をすぐに表示し、ぼかしと変形を解除して、ピン留めも解除します。- スクリーンリーダーで自然に読み上げられるようにし、単語ごとに読み上げないようにします。
- 非表示状態と表示完了状態の両方でコントラストを確認します。非表示の単語は目立たなくてもかまいませんが、表示されたテキストは通常の読みやすさの基準を満たす必要があります。
クリーンアップする
ルートの変更時またはコンポーネントのアンマウント時に、ScrollTrigger を破棄し、スクロールとリサイズのリスナーを削除し、アニメーションフレームをキャンセルして、マークアップを含む元のサブツリーを復元します。開始位置または終了位置がテキストの寸法に依存する場合は、フォントの読み込み後に計測値を更新します。
検証する
インラインリンクと強調表示、句読点、連続する空白、長い単語、200% ズーム、幅 390/768/1440、コンテンツの変更、前方向と逆方向のスクロール、動きを減らす設定、キーボードフォーカス、スクリーンリーダーの読み上げ順、後処理をテストします。JavaScript を無効にしても、最終的な DOM から文全体を理解できる必要があります。
実装の作業用リファレンスとして demo/index.html を使用し、再作成またはリミックスするには demo/PROMPT.md を使用します。REFERENCES.md はリンクのみの実装ソース一覧として保持します。