アニメーション
インターフェースにおけるモーションは、何が起こったのかを説明します:要素がどこから来たのか、どこへ行ったのか、プレスが認識されたかどうか。これを行わないものはすべて装飾であり、装飾には小さな予算しかありません。このスキルはその予算を正確に使うのに役立ちます。これがないと、モデルはすべてを同じフェードアップでアニメーションさせてしまいます。
このスキルは自己完結型です。もし ui-ux(スタイルとインターフェースのルール)と front(コードとスタック)が一緒にインストールされていれば、それらを補完します。
最初の3つの質問
- このモーションの目的は? アクションに対するフィードバック、状態間のリンク、重要なものへの注意喚起、ブランドの特性。答えがなければ、アニメーションさせないでください。
- ユーザーはそれをどのくらいの頻度で見るのか? 予算はその答えに依存します(次のセクション)。
- プロジェクトには何が既にあるのか? 使用されている継続時間、カーブ、アニメーションライブラリを確認し、同じ精神で続けてください。たった一つのエフェクトのために新しいライブラリを導入するのは、ほとんどの場合間違いです。
適切なアニメーションの量
主なルール:アクションの頻度が高いほど、アニメーションは少なく。 初めて見たときに喜ばれるものも、100回目にはイライラさせます。
| ユーザーが見る頻度 | すべきこと |
|---|---|
| 1日に何百回(キーボードショートカット、コマンドパレット、タブ切り替え) | アニメーションなし |
| 1日に何十回(メニュー、ツールチップ、ホバー) | 非常に速く、最大150ms、またはアニメーションなし |
| たまに(ダイアログ、サイドパネル、通知) | 通常の200~300msのトランジション |
| めったに、または一度だけ(オンボーディング、成功画面、ランディングページの最初の画面) | 表現力を高めてよい |
プロジェクトタイプ別のレベル:
- アプリ(毎日使われる):控えめに。コントロールの状態、レイヤーの出入り、スムーズなレイアウト変更。すべて300ms以下。ユーザーのアクションなしには何も動きません。
- ショーケース(ランディングページ、ウェブサイト、プロモーション):目立つように。最初の画面での一つの演出された瞬間、スクロールで現れるブロック、ホバー時の生き生きとしたディテール。残りは静かに。
画面ごとに一つの表現力豊かな瞬間、他の場所は静かに。 すべてを同時にアニメーションさせるのは、アニメーションがないのと同じくらいテンプレートの兆候です。
アニメーションさせないもの:キーボードトリガーのアクション、テーマ切り替え、コンテキストメニュー、ユーザーが連続して何度も行うものすべて。
デフォルトのテイスト
スキルの所有者は、このセクションを自分の好みに合わせて編集できます。現在のリクエストにおけるユーザーの言葉が優先されます。
ショーケースサーフェスで歓迎されるもの:
- スクロールでの表示 — セクションや大きなオブジェクトが、スクロールされたときにソフトに現れます。一度だけ、繰り返しなし。
- スクロール連動シーン — スクロールがアニメーションを駆動し、製品について何かを説明する固定セクション。ページごとに1つか2つ。スクロール自体は通常のままで、その速度や方向が乗っ取られることは決してありません。
明示的に要求されなければ使用しないもの:
- グローとグラデーションボーダー — きらめくアウトライン、ネオングロー、アニメーションするグラデーション背景。強調はモーションとタイポグラフィから来るものであり、光から来るものではありません。
ライブラリ: CSS優先。Reactで不十分な場合はMotion。複雑なスクロールシーンの場合のみGSAP。詳細は references/tools.md にあります。
モーションの特徴は「接続され、正確」。
- アプリ内のフロー。 画面は切り替わるのではなく、互いに溶け込みます:1つの「ヒーロー」オブジェクトがすべてのステップを通り抜け、テキストはブラーを通してテキストに変わり、変更されたものだけが変化し、新しいレイヤーはそのソースから成長します。タスクに一連の画面や状態がある場合は、最初に
references/continuity.mdを読み、ヒーローを割り当ててください。 - ランディングページとウェブサイト。 サイト全体で1つのカーブを使用し、鋭いスタートと長くソフトな減速、バウンスなし。見出しは単語ごとに組み立てられます。大きなものはブラーから現れます。スクロールに応じたテキストシーンが1つ。すべてCSS。正確な値を使ったレシピは
references/showcase-recipes.mdにあります。
両方に共通するもの:トランジションの素材としてのブラーと不透明度の組み合わせ、キューではなく重なるエントリーとイグジット、バウンスなし、そして一貫した1つのカーブ。プロジェクトのスタイルが異なる特性(ターミナル、レトロ)を求める場合は、references/patterns.md の表を参照してください。
継続時間
| 何 | 継続時間 |
|---|---|
| プレス、ホバー、トグル自体への応答 | 100–150ms |
| ツールチップ、ドロップダウンメニュー、小さなエントリー | 150–200ms |
| ダイアログ、パネル、シート | 200–300ms |
| アクションに応じたコンテンツの変更(価格、カウンター、チャート) | 300–500ms |
| ページ遷移、大きなレイアウト変更 | 300–500ms |
| ユーザーの関与のないショーケースサーフェス上の装飾的なシーン | 最大800–1000ms |
- イグジットはエントリーより約3分の1短く: 出て行くものはもはや興味を引かない。
- パスが長く、面積が大きいほど、継続時間も長く。 小さな要素が400msでは鈍く見える。
- ルールが重なる場合は、短い方が勝ち。 コントロール自体は常に100–150msで応答します。コントロールが変更したものは完了までに時間がかかるかもしれませんが、ユーザーはアニメーションが終了するのを待ってから再び操作する必要はありません。
カーブとスプリング
- エントリー — ease-out: 速いスタートとソフトなストップ。応答性が感じられます。
- イグジット — 同様にease-outだが、より短く。 一部のデザインシステムはイグジットに加速カーブを使用しますが、その遅いスタートは遅延のように感じられるため、ここでは使用しません。スキル所有者はこのルールを変更できます。
- 画面上をポイントからポイントへ移動する — ease-in-out。
- リニア — 継続的なモーションのみ: 回転インジケーター、マーキー、プログレス。
デフォルトトークン:
:root {
--ease-out: cubic-bezier(0.23, 1, 0.32, 1); /* メインカーブ:鋭いスタート、長い減速 */
--ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
--duration-fast: 160ms; /* 応答:色、不透明度 */
--duration-base: 300ms; /* レイヤー、コントロールの背景と影 */
--duration-slow: 450ms; /* コンテンツがコンテンツに溶け込む */
--duration-reveal: 800ms; /* ショーケースサーフェス上でブロックが現れる */
}
プロジェクト全体で1つのカーブ:トランジションのすべての部分がそれを使用すると、それらは単一の動きとして読み取られます。このカーブでは、応答は200-450ms持続しても即座に感じられます。なぜなら、変化のほとんどが最初の100msで起こるからです。
スプリングは、ジェスチャーがモーションを駆動する場合や、アニメーションが途中で中断される可能性がある場合(ドラッグ、シート、リストの並べ替え)にカーブよりも優れています: 速度を保持し、ぎくしゃくしません。バウンスは動きとスケールにのみ使用します。色と不透明度には常にゼロ。目立つバウンスは遊び心のあるスタイルに適しており、作業ツールではイライラさせます。
実行ルール
transformとopacityをアニメーションさせる。 幅、高さ、マージン、位置はレイアウトの再計算をトリガーし、カクつきを引き起こします。サイズを変更するには、scale、FLIPテクニック、またはライブラリのレイアウトアニメーションを使用します。- ブラーは許可された例外です。
filter: blur()(最大12px)と不透明度の組み合わせは、トランジションの特徴的な素材ですが、コストがかかります:小さなブロック(見出し、図、アイコン、カード)にのみ適用し、画面全体には決して適用せず、スマートフォンでテストしてください。 - エントリーとイグジットは重なる。 出て行くものと現れるものは、継続時間の30~50%の間共存します。「最初に消えて、それから現れる」というキューは、接続を断ち切り、時間を2倍にします。
- 変更された部分だけが動く。 変更されなかったもの(数字、単語、アイコン)はそのまま残ります。
scale(0)から開始しない。 現実のものは点から現れません。0.9~0.96から不透明度とともに開始します。transform-originはソースに配置する。 メニューはボタンから成長し、中央からではありません。- プレス:
:activeでscale(0.97)は、物理的なボタンの感触を与えます。 - 中断可能性。 インタラクティブなモーションは
transitionで構築し、@keyframesは使用しないでください。トランジションは途中で逆転できますが、キーフレームはできません。 - 役割が先、タイミングは後。 複数の要素が1つのイベントに応じて動く場合、単一のリーダーを割り当てます。残りはサポート、装飾、または静的です。リーダーが2ついるのはレイアウトの問題であり、アニメーションの問題ではありません。
- コンテナごとに1つのエントリー。 パネルがスライドインした場合、そのコンテンツはすでにそこにあります。親のエントリーの上に子のスタッガーを追加しないでください。
- 出て行くものはすぐにそのスペースを解放するため、 隣接要素はフェードアウト中に(その後ではなく)詰められます。
- イグジットはエントリーをミラーリングし、一度にすべて発生する。 右から入ってきたものは右に出て行きます。グループは同時に消え、逆スタッガーはありません。
- 方向は意味に従う: 「進む」は右から、「戻る」は左から。
- スタッガー: 要素間の30~80msのステップ。カスケード全体は300~400ms以内。6番目または7番目の要素以降は、残りは一緒に現れます。ショーケースの最初の画面では、ステップは100~150msまで上がることがあります。
- ジェスチャーはスプリングを使用し、決してブロックしない。 要素は指に1対1で追従し、途中で掴むことができ、解放後はジェスチャーの速度を受け継ぎます。バウンスはスローイングの後だけです。
- ツールチップ: 最初のツールチップの前には遅延を入れ、同じグループ内の次のツールチップは即座にアニメーションなしで表示します。
- スクロールでの表示は一度だけ。 ブロックがパスごとに非表示になり再表示されるのは疲れます。
- ページは静止時に完全であること。 コンテンツはスクリプトが実行されたかどうかに依存してはいけません。非表示の開始状態は、アニメーションが有効になっている場合にのみ設定され、基本スタイルでは決して設定しません。そうしないと、スクリプトが失敗した場合、プレビューやスクリーンショットで、ユーザーは空の画面を見ることになります。
- ホバーは一度に1つのプロパティのみを変更し、 スケール、リフト、シャドウをすべて同時に変更しない。
will-change— 控えめに、そしてアニメーションの間だけ。すべてに設定しない。
アクセシビリティ
これはオプションではありません。画面上のモーションは、一部の人にめまいや吐き気を引き起こします。
prefers-reduced-motion: reduce: 動き、スケール、回転、パララックス、自動再生を削除。不透明度と色のスムーズな変更は維持する。すべてをオフにすると、その人からフィードバックを奪うことになります。最も信頼性の高いアプローチは、許可されている場所にのみモーションを宣言することです:
.card { transition: opacity var(--duration-base) var(--ease-out), background-color var(--duration-fast); }
@media (prefers-reduced-motion: no-preference) {
.card { transition-property: opacity, background-color, transform; }
.card:hover { transform: translateY(-2px); }
}
- 5秒以上自律的に動くもの(マーキー、カルーセル、背景動画)には、一時停止ボタンが必要です — WCAG 2.2.2の要件。
- 1秒間に3回以上点滅するものはありません。
- 広い範囲でのモーション(パララックス、背景のスケーリング)は、振幅を小さく保ちます。
- アニメーションするテキストは、スクリーンリーダーが読み取れるようにします。文字ごとに分割されたものには、フレーズ全体を含む
aria-labelを付け、分割された部分にはaria-hiddenを付けます。
検証
- アニメーションはコードだけでなく、ブラウザで確認してください。確認できない場合は、ライブで確認していないことをユーザーに伝えてください。
- 開発者ツールで4~10倍にスローダウンする:カクつき、不適切な成長の原点、不要なプロパティが見えるようになります。
- 素早く数回連続して押す:アニメーションは中断して逆転し、キューに積み重なってはいけません。
- システムで「動きを減らす」をオンにし、インターフェースがまだ機能し、理解可能であることを確認します。
- スクロール直後に撮影したスクリーンショットには、ブロックがまだ表示されていない空のスペースが表示される場合があります。これは「ページは静止時に完全であること」のルールを確認する理由です。
レビューモード
既存のアニメーションを評価または修正するよう求められた場合は、調査結果を表として報告します:
| 場所 | 変更前 | 変更後 | 理由 |
|---|---|---|---|
Modal.tsx:18 | scale(0) → 1, 500ms, ease-in | scale(0.96) + opacity, 220ms, ease-out | 点から現れ、遅延している |
参考ファイル
references/continuity.md— 接続されたアニメーション:フローのヒーロー、互いに溶け合う画面、数字が桁ごとに変化する、スクロールで折りたたむ。そのテクニックとウェブ上での構築方法。一連の画面や状態がある場合は読んでください。references/choreography.md— 1つのイベントに反応する要素のグループ:役割(リーダー、サポート、装飾、静的)、ペア内の関係(一緒に、重なり、順序、運ぶ)、スタッガー、方向、イグジット、中断。複数の要素が動くときはいつでも読んでください。references/gestures.md— ドラッグ、スワイプ、スローされるすべてのもの:指の追跡、中断可能性、スプリング、速度の引き継ぎ、モメンタムの投影、ソフトバウンダリー。シート、カルーセル、スライダー、ドラッグアンドドロップのために読んでください。references/showcase-recipes.md— 正確な値を使ったランディングページのレシピ:単語ごとの見出し、ブラーからの出現、描かれる下線、カードのカスケード、スクロール上のテキスト。サイトの最初の画面とセクションのために読んでください。references/patterns.md— テクニックのカタログ:マイクロインタラクション、エントリー、数値変化、スクロール、ページ遷移、テキスト。それぞれがいつ機能し、いつ害になるか。スタイルによるモーションの特性。references/tools.md— CSSからGSAPまでのツールラダーとコード例、選択ルール。