mcpField
U
ui-animation

ui-animation

github.com/travisjneumanデザイン・UI106293 回インストール今日更新
リポジトリ

ui-animation について

UI デザイナーや開発者向けのアニメーション設計ガイドです。動きの原則、実装パターン、パフォーマンス、アクセシビリティを扱い、目的に沿った UI アニメーションの設計に役立ちます。

主な機能

  1. 01動きの原則と時間の目安
  2. 02イージング関数とアニメーションパターン
  3. 03CSS と JavaScript の実装例
  4. 04パフォーマンス指針と FLIP 手法
  5. 05動きを減らす設定とアクセシビリティへの配慮

活用シーン

  1. 01ボタンやトグルのマイクロインタラクション設計
  2. 02ローディング表示やページ遷移の設計
  3. 03アニメーション性能と動きを減らす設定の確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/travisjneuman/.claude --skill ui-animation

インストール後、Claude Code で/ui-animationを入力して読み込まれたか確認します。

詳細

UIアニメーションとモーションデザイン

ユーザーインターフェースで、目的に沿った高パフォーマンスなアニメーションを作成するための包括的なガイドです。

アニメーションの原則

アニメーションの12原則(UIへの応用)
原則UIへの応用
タイミング重要度や距離を期間に反映します
イージング自然な加速と減速を表現します
予備動作アクションのための視覚的な準備
後続動作停止後も勢いが続きます
二次アクション補助要素が反応します
演出重要な要素に注目を集めます
スクワッシュ&ストレッチ弾むような楽しいインタラクション
誇張重要なフィードバックを強調します
弧自然な曲線の動きの軌跡
オーバーラップ要素が異なる速度で動きます
立体感のある描画一貫した3D空間を保ちます
魅力人を引きつける、心地よい動き
アニメーションを使う理由
FUNCTIONAL PURPOSES:
✓ Guide attention to important changes
✓ Show relationships between elements
✓ Provide feedback for actions
✓ Communicate system status
✓ Ease cognitive load
✓ Create spatial orientation

NOT FOR:
✗ Pure decoration
✗ Showing off skills
✗ Making things "feel modern"
✗ Distracting from content

タイミングと期間

期間のガイドライン
INSTANT (0-100ms):
└─→ Button state changes
└─→ Toggle switches
└─→ Micro-feedback

FAST (100-200ms):
└─→ Hover effects
└─→ Simple fades
└─→ Small movements

STANDARD (200-300ms):
└─→ Most UI transitions
└─→ Modal open/close
└─→ Dropdown menus

SLOW (300-500ms):
└─→ Complex transitions
└─→ Page transitions
└─→ Large element movement

DELIBERATE (500ms+):
└─→ Hero animations
└─→ Skeleton loading
└─→ Onboarding sequences
距離に基づくタイミング
Rule: Longer distance = Longer duration

Small (< 100px):   150-200ms
Medium (100-300px): 200-300ms
Large (300-500px):  300-400ms
Full screen:        400-500ms

Formula:
duration = baseTime + (distance × factor)

イージング関数

標準的なイージング
LINEAR
├────────────────────────────┤
Constant speed. Rarely natural.
Use: Progress bars, clock hands

EASE-OUT (Deceleration)
├═══════════────────────────┤
Fast start, slow end.
Use: Elements entering the screen

EASE-IN (Acceleration)
├────────────────═══════════┤
Slow start, fast end.
Use: Elements leaving the screen

EASE-IN-OUT (S-curve)
├────═══════════════────────┤
Slow start and end, fast middle.
Use: On-screen transitions

EASE-OUT-BACK (Overshoot)
├═══════════────────────╗───┤
Overshoots, settles back.
Use: Playful entrances, bounces
CSSイージング値
/* Built-in keywords */
linear: cubic-bezier(0, 0, 1, 1)
ease: cubic-bezier(0.25, 0.1, 0.25, 1)
ease-in: cubic-bezier(0.42, 0, 1, 1)
ease-out: cubic-bezier(0, 0, 0.58, 1)
ease-in-out: cubic-bezier(0.42, 0, 0.58, 1)

/* Material Design standard */
standard: cubic-bezier(0.4, 0, 0.2, 1)
decelerate: cubic-bezier(0, 0, 0.2, 1)
accelerate: cubic-bezier(0.4, 0, 1, 1)

/* Custom: Snappy */
snappy: cubic-bezier(0.5, 0, 0, 1)

/* Custom: Bouncy */
bouncy: cubic-bezier(0.68, -0.55, 0.27, 1.55)

/* Spring-like (use JS libraries) */
spring: { stiffness: 300, damping: 20 }
使い分け
シナリオイージング理由
要素の表示ease-out勢いよく現れ、落ち着きます
要素の非表示ease-in退出に向けて勢いをつけます
画面上の変化ease-in-out状態が滑らかに変化します
注意を引くbounce/spring楽しく、目立ちます
背景/控えめな演出ease-out目立ちません

アニメーションのパターン

マイクロインタラクション
BUTTON STATES:
┌─────────────────────────────────────────┐
│ Rest → Hover: scale(1.02), 100ms        │
│ Hover → Active: scale(0.98), 50ms       │
│ Active → Rest: scale(1), 150ms ease-out │
└─────────────────────────────────────────┘

TOGGLE SWITCH:
┌─────────────────────────────────────────┐
│ Thumb: translateX, 200ms ease-out       │
│ Track: background-color, 200ms          │
│ State: slight bounce at end             │
└─────────────────────────────────────────┘

CHECKBOX:
┌─────────────────────────────────────────┐
│ Check mark: stroke-dashoffset animation │
│ Background: scale from center, 150ms    │
│ Ripple: expanding circle, 300ms         │
└─────────────────────────────────────────┘
ローディング状態
SKELETON SCREENS:
┌──────────────────────────┐
│ ▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░  │ Shimmer effect
│ ▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░  │ Linear gradient
│ ▓▓▓▓▓▓░░░░░░░░░░░░░░░░  │ Moving left to right
└──────────────────────────┘

CSS:
background: linear-gradient(
  90deg,
  #f0f0f0 25%,
  #e0e0e0 50%,
  #f0f0f0 75%
);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;

SPINNER:
- Duration: 1-2 seconds per rotation
- Easing: linear (consistent motion)
- Style: Match brand identity
ページ遷移
CROSSFADE:
├──────────────────────────────────────────┤
│ Old page: opacity 1 → 0, 200ms           │
│ New page: opacity 0 → 1, 200ms           │
│ Timing: Sequential or overlapping        │
└──────────────────────────────────────────┘

SLIDE:
├──────────────────────────────────────────┤
│ Direction follows navigation hierarchy   │
│ Forward: Slide left (new from right)     │
│ Back: Slide right (prev from left)       │
│ Duration: 300-400ms                      │
└──────────────────────────────────────────┘

SHARED ELEMENT:
├──────────────────────────────────────────┤
│ Element morphs between states            │
│ Position, size, border-radius change     │
│ Creates continuity between screens       │
│ Duration: 300-500ms                      │
└──────────────────────────────────────────┘
リストアニメーション
STAGGERED ENTRANCE:
┌─ Item 1 ────────────────┐  delay: 0ms
├─ Item 2 ────────────────┤  delay: 50ms
├─ Item 3 ────────────────┤  delay: 100ms
├─ Item 4 ────────────────┤  delay: 150ms
└─ Item 5 ────────────────┘  delay: 200ms

Max total duration: 500ms
Stagger: 30-50ms per item
Animation: translateY + opacity

REORDER:
- Use FLIP technique
- Duration: 200-300ms
- Ease: ease-out

パフォーマンス

GPUアクセラレーション対応プロパティ
FAST (Compositor only):
✓ transform: translate, scale, rotate
✓ opacity
✓ filter (with will-change)

SLOW (Triggers layout/paint):
✗ width, height
✗ margin, padding
✗ top, left, right, bottom
✗ border, border-radius
✗ font-size
✗ box-shadow (repaints)

OPTIMIZATION:
will-change: transform, opacity;
/* Use sparingly! */
パフォーマンスのガイドライン
/* Good: GPU-accelerated */
.animated-element {
  transform: translateX(0);
  transition: transform 300ms ease-out;
}
.animated-element.moved {
  transform: translateX(100px);
}

/* Bad: Layout thrashing */
.animated-element {
  left: 0;
  transition: left 300ms ease-out;
}
.animated-element.moved {
  left: 100px;
}
FLIPテクニック
// First: Get initial position
const first = element.getBoundingClientRect();

// Last: Apply change, get final position
element.classList.add("moved");
const last = element.getBoundingClientRect();

// Invert: Calculate delta, apply inverse transform
const deltaX = first.left - last.left;
const deltaY = first.top - last.top;
element.style.transform = `translate(${deltaX}px, ${deltaY}px)`;

// Play: Remove transform with transition
requestAnimationFrame(() => {
  element.style.transition = "transform 300ms ease-out";
  element.style.transform = "";
});

CSSアニメーションのテクニック

キーフレームアニメーション
@keyframes fadeSlideIn {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.element {
  animation: fadeSlideIn 300ms ease-out forwards;
}

/* With steps */
@keyframes typewriter {
  from {
    width: 0;
  }
  to {
    width: 100%;
  }
}

.typing-text {
  animation: typewriter 2s steps(20) forwards;
}
トランジション
.button {
  background: var(--primary);
  transform: scale(1);
  transition:
    background 150ms ease-out,
    transform 100ms ease-out;
}

.button:hover {
  background: var(--primary-hover);
  transform: scale(1.02);
}

.button:active {
  transform: scale(0.98);
  transition-duration: 50ms;
}
animationのショートハンド
/* animation: name duration timing-function delay
              iteration-count direction fill-mode play-state */

animation: slideIn 300ms ease-out 100ms 1 normal forwards running;

/* Common patterns */
animation: spin 1s linear infinite;
animation: pulse 2s ease-in-out infinite alternate;
animation: fadeIn 300ms ease-out forwards;

JavaScriptアニメーションライブラリ

比較
ライブラリ最適な用途バンドルサイズ
CSSシンプルなトランジション0kb
Web Animations APIネイティブで高パフォーマンス0kb
GSAP複雑で精密なアニメーション~60kb
Framer MotionReactエコシステム~50kb
anime.jsタイムライン、SVG~17kb
Motion Oneモダンで軽量~18kb
LottieAfter Effectsからの書き出し~50kb
Framer Motion(React)
import { motion, AnimatePresence } from "framer-motion";

// Basic animation
<motion.div
  initial={{ opacity: 0, y: 20 }}
  animate={{ opacity: 1, y: 0 }}
  exit={{ opacity: 0, y: -20 }}
  transition={{ duration: 0.3, ease: "easeOut" }}
>
  Content
</motion.div>;

// Variants for complex animations
const containerVariants = {
  hidden: { opacity: 0 },
  visible: {
    opacity: 1,
    transition: {
      staggerChildren: 0.1,
    },
  },
};

const itemVariants = {
  hidden: { opacity: 0, y: 20 },
  visible: { opacity: 1, y: 0 },
};

<motion.ul variants={containerVariants} initial="hidden" animate="visible">
  {items.map((item) => (
    <motion.li key={item.id} variants={itemVariants}>
      {item.name}
    </motion.li>
  ))}
</motion.ul>;
GSAP
import { gsap } from "gsap";

// Basic tween
gsap.to(".element", {
  x: 100,
  opacity: 1,
  duration: 0.3,
  ease: "power2.out",
});

// Timeline
const tl = gsap.timeline();
tl.from(".header", { y: -100, duration: 0.5 })
  .from(".content", { opacity: 0, duration: 0.3 }, "-=0.2")
  .from(".button", { scale: 0.8, duration: 0.2 });

// ScrollTrigger
gsap.registerPlugin(ScrollTrigger);
gsap.to(".parallax", {
  y: -100,
  scrollTrigger: {
    trigger: ".section",
    start: "top center",
    end: "bottom center",
    scrub: true,
  },
});

アクセシビリティ

ユーザーの設定を尊重する
/* Reduce motion for users who prefer it */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* Or provide simpler alternatives */
@media (prefers-reduced-motion: reduce) {
  .animated-element {
    /* Replace motion with opacity */
    animation: none;
    transition: opacity 200ms ease;
  }
}
安全なアニメーションの実践
AVOID for vestibular disorders:
✗ Parallax scrolling effects
✗ Zooming/scaling animations
✗ Spinning/rotating elements
✗ Auto-playing animations
✗ Flashing (>3 times/second)

SAFE alternatives:
✓ Opacity fades
✓ Color transitions
✓ Subtle position changes
✓ User-initiated animations
WCAGガイドライン
2.2.2 Pause, Stop, Hide:
- Auto-updating content can be paused
- No time limits on reading

2.3.1 Three Flashes:
- Nothing flashes more than 3x per second

2.3.3 Animation from Interactions:
- Motion can be disabled
- Triggered animations respect preferences

モバイルでの考慮事項

タッチフィードバック
/* iOS-style tap feedback */
.button {
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

.button:active {
  opacity: 0.7;
  transition: opacity 50ms;
}

/* Ripple effect */
.ripple {
  position: relative;
  overflow: hidden;
}

.ripple::after {
  content: "";
  position: absolute;
  background: rgba(255, 255, 255, 0.3);
  border-radius: 50%;
  transform: scale(0);
  animation: ripple 400ms ease-out;
}
プラットフォームごとの慣習
プラットフォームアニメーションスタイル
iOSスプリング物理、300-500ms、控えめ
AndroidMaterial motion、200-300ms、強調
Webさまざま、通常は200-400ms

デザインシステムへの統合

アニメーションのトークン
:root {
  /* Durations */
  --duration-instant: 100ms;
  --duration-fast: 150ms;
  --duration-normal: 250ms;
  --duration-slow: 400ms;
  --duration-slower: 600ms;

  /* Easings */
  --ease-default: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-in: cubic-bezier(0.4, 0, 1, 1);
  --ease-out: cubic-bezier(0, 0, 0.2, 1);
  --ease-bounce: cubic-bezier(0.68, -0.55, 0.27, 1.55);

  /* Combined */
  --transition-default: var(--duration-normal) var(--ease-default);
  --transition-fast: var(--duration-fast) var(--ease-out);
}

/* Usage */
.element {
  transition: transform var(--transition-default);
}

ベストプラクティス

DO:
  • 目的(フィードバック、ガイダンス)を持ってアニメーションを使います
  • GPUアクセラレーション対応プロパティを使います
  • 期間を500ms未満に保ちます
  • アニメーションをブランドの個性に合わせます
  • prefers-reduced-motionを尊重します
  • ローエンド端末でテストします
  • 一貫したタイミングシステムを使います
してはいけないこと:
  • 装飾だけを目的にアニメーションを使う
  • ユーザーの操作を妨げる
  • 過度なバウンスやオーバーシュートを使う
  • モーション酔いを引き起こす動きを作る
  • 終了アニメーションを忘れる
  • パフォーマンス指標を無視する
  • 重要なコンテンツの表示を遅らせる

アニメーションチェックリスト

実装前
  • アニメーションに目的がある
  • 動作に適した時間になっている
  • イージングが動きの意図に合っている
  • パフォーマンスへの影響を評価している
実装
  • GPU アクセラレーションに対応したプロパティを使用している
  • prefers-reduced-motion を尊重している
  • 対象デバイスで動作する
  • レイアウトのスラッシングが発生しない
品質チェック
  • 自然で応答性が高い
  • ユーザーを待たせない
  • デザインシステムとの一貫性がある
  • すべてのユーザーが利用できる

コメント