Tips & Tricks (更新: 2026/6/3)

Claude CodeでUIアニメーションを安全に実装する実務ガイド

Claude Codeで軽く壊れにくいUIアニメーションを作る手順。CSS、JS、落とし穴、検証方法まで解説。

Claude CodeでUIアニメーションを安全に実装する実務ガイド

この記事で作るもの

Claude CodeでUIアニメーションを実装するとき、最初に決めるべきことは「どこを動かすか」ではなく「何を助ける動きなのか」です。アニメーションは装飾ではなく、読者に次の行動を伝えるフィードバックです。保存できた、エラーが出た、次に読むべきカードがある、資料請求ボタンが主要な導線である。このような意味を、本文やボタンを邪魔しない範囲で補助するのが安全なUIアニメーションです。

初心者がClaude Codeに「いい感じにアニメーションを入れて」と頼むと、見た目は整っても、スマホで横スクロールが出る、キーボード操作でフォーカス位置が分からない、prefers-reduced-motionを無視する、既存のデザイントークンを使わない、といった問題が出やすくなります。この記事では、CSSと小さなJavaScriptだけで、スクロール時の表示、ボタンの反応、状態変化を安全に入れる方法を扱います。

関連する土台は Claude CodeデザインシステムClaude CodeレスポンシブデザインClaude Codeパフォーマンス最適化 も合わせて確認してください。公式情報は Claude Code docsMDNのCSS animationMDNのIntersection Observer APIMDNのprefers-reduced-motionweb.devのCSS animations を参照します。Intersection Observerは、要素が画面に入ったかをブラウザが効率よく通知するAPIです。prefers-reduced-motionは、端末側で「動きを減らしたい」と設定しているユーザーに合わせるCSSの仕組みです。

Claude Codeへの依頼文

まずClaude Codeへ渡す依頼を小さくします。実務では、アニメーションを1回で全画面へ広げるより、1つのセクションで安全に動かし、レビューしてから横展開する方が失敗しません。

この画面に軽量なUIアニメーションを追加してください。
対象はCTA直前のカード、読み込み完了後のセクション、保存ボタンの反応だけです。
既存コンポーネント、既存CSS変数、ルーティング、文言は壊さないでください。
CSSと小さなJSを優先し、不要なライブラリは追加しないでください。
ユースケース、落とし穴、アクセシビリティ、prefers-reduced-motion、375px幅での確認結果を返してください。

この依頼文で重要なのは、対象、禁止事項、確認観点を明示している点です。Claude Codeは広い指示を受けると、周辺コンポーネントや全体レイアウトまで触ることがあります。公開済みサイトでは、変更ファイルが増えるほどレビューの難度が上がります。特に記事ページ、商品カード、研修申込フォームのような収益導線では、動きの気持ちよさよりも、読者が迷わず次へ進めることを優先します。

ユースケース(実務で効く使いどころ)

ユースケース目的動かす場所成功条件
記事下の回遊関連記事や商品への導線を見つけてもらう関連カード、CTA直前の補足本文の読了を邪魔しない
SaaS管理画面保存、同期、エラーの状態をすぐ伝えるボタン、トースト、空データ色だけで意味を伝えない
商品ページ価格表や購入ボタンへ視線を誘導する比較表、特典カード、CTA購入ボタンが隠れない
チーム開発Claude Codeの差分レビューを短くする実装対象を限定する変更理由と確認結果が残る

1つ目のユースケースは、ブログや解説記事の末尾です。読者が実装手順を読み終えた直後に、ClaudeCodeLabの製品Claude Code研修・相談 を自然に見つけられると、広告や派手なバナーに頼らず導線を作れます。ただし、本文中のコードブロックより目立つ動きは逆効果です。読者はコードをコピーしたいので、CTAが跳ね続けると集中を削ります。

2つ目は管理画面です。保存ボタンを押したあと、ボタンが軽く縮み、完了時にラベルが「保存しました」へ変わるだけでも操作の不安は減ります。ここで重要なのは、アニメーションだけで成功を伝えないことです。スクリーンリーダー向けの状態テキスト、キーボードフォーカス、エラー文言を残しておきます。

3つ目は商品ページです。価格表、比較表、特典カードは情報量が多く、読者がどこから見ればよいか迷いやすい領域です。カードを順番にフェードインさせると視線誘導になりますが、遅すぎる表示は購入判断を待たせます。目安として、装飾的な表示は200から500ミリ秒に収め、ユーザー操作の結果は即時に返します。

4つ目はチームレビューです。Claude Codeに「アニメーションを追加」だけでなく「どのユースケースに効くか、どの落とし穴を避けたか」まで説明させると、レビュー担当は見た目の好みではなく、目的に対して判断できます。

実装の全体像

安全な実装は、次の3層に分けると扱いやすくなります。

役割Claude Codeに確認させること
HTML何を動かすかを属性で示す見出し、本文、CTAの意味が残っているか
CSS透明度、移動量、時間、減速曲線を定義するtransformopacity中心で重くないか
JS表示タイミングと後片付けを制御する監視解除、未対応ブラウザ、reduce motion対応

この分け方にすると、Claude Codeの差分も読みやすくなります。HTMLはdata-revealを付けるだけ、CSSは共通クラスへ閉じる、JSは初期化関数にする、という境界ができます。後からReact、Astro、Next.jsへ移しても、考え方はほぼ同じです。

コピペで試せるHTML

次のHTMLは、記事ページや商品ページの一部としてそのまま使える最小例です。実際のプロジェクトでは、既存のカードコンポーネントにdata-revealrevealクラスだけを足す形にしてください。

<section class="motion-demo" aria-labelledby="motion-demo-title">
  <p class="eyebrow">ClaudeCodeLab workflow</p>
  <h2 id="motion-demo-title">安全なUIアニメーションの導入</h2>
  <p>
    目的、対象、検証方法を先に決めてから、Claude Codeに小さな差分で実装させます。
  </p>

  <div class="motion-grid">
    <article class="reveal" data-reveal>
      <h3>設計</h3>
      <p>ユースケースと成功条件を1つに絞ります。</p>
    </article>
    <article class="reveal" data-reveal>
      <h3>実装</h3>
      <p>CSS変数と小さなJSで、既存UIを壊さず追加します。</p>
    </article>
    <article class="reveal" data-reveal>
      <h3>検証</h3>
      <p>落とし穴、reduce motion、スマホ幅、キーボード操作を確認します。</p>
    </article>
  </div>

  <a class="motion-cta reveal" data-reveal href="/training/">
    Claude Code研修で相談する
  </a>
</section>

コピペで動くCSS

CSSはopacitytransformを中心にします。widthheighttopleftをアニメーションさせるとレイアウト計算が増えやすく、記事ページのスクロールや広告枠に影響することがあります。will-changeは便利ですが、付けっぱなしにするとメモリを使うため、対象を限定します。

:root {
  --motion-duration: 420ms;
  --motion-distance: 16px;
  --motion-ease: cubic-bezier(0.16, 1, 0.3, 1);
  --motion-border: #d8e2ee;
  --motion-bg: #ffffff;
  --motion-text: #182230;
  --motion-accent: #2563eb;
}

.motion-demo {
  color: var(--motion-text);
  max-width: 920px;
  margin: 48px auto;
  padding: 24px;
}

.eyebrow {
  margin: 0 0 8px;
  color: var(--motion-accent);
  font-weight: 700;
}

.motion-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
  margin: 24px 0;
}

.motion-grid article {
  border: 1px solid var(--motion-border);
  border-radius: 8px;
  background: var(--motion-bg);
  padding: 16px;
}

.reveal {
  opacity: 0;
  transform: translateY(var(--motion-distance));
  transition:
    opacity var(--motion-duration) var(--motion-ease),
    transform var(--motion-duration) var(--motion-ease);
  will-change: opacity, transform;
}

.reveal.is-visible {
  opacity: 1;
  transform: translate3d(0, 0, 0);
}

.motion-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 18px;
  border-radius: 8px;
  background: var(--motion-accent);
  color: #ffffff;
  font-weight: 700;
  text-decoration: none;
}

.motion-cta:focus-visible {
  outline: 3px solid #f59e0b;
  outline-offset: 3px;
}

@media (max-width: 640px) {
  .motion-demo {
    margin: 32px auto;
    padding: 16px;
  }

  .motion-grid {
    grid-template-columns: 1fr;
  }
}

@media (prefers-reduced-motion: reduce) {
  .reveal {
    opacity: 1;
    transform: none;
    transition: none;
    will-change: auto;
  }
}

コピペで動くJavaScript

JavaScriptではIntersection Observerを使います。スクロールイベントを毎回監視して位置を計算するより、ブラウザに表示判定を任せる方がシンプルです。未対応ブラウザやreduce motionのユーザーには、最初から表示済みにします。

export function setupScrollReveal(root = document) {
  const targets = Array.from(root.querySelectorAll("[data-reveal]"));
  const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;

  if (targets.length === 0) {
    return () => {};
  }

  if (reduceMotion || !("IntersectionObserver" in window)) {
    targets.forEach((target) => target.classList.add("is-visible"));
    return () => {};
  }

  const observer = new IntersectionObserver(
    (entries) => {
      for (const entry of entries) {
        if (!entry.isIntersecting) continue;
        entry.target.classList.add("is-visible");
        observer.unobserve(entry.target);
      }
    },
    {
      root: null,
      rootMargin: "0px 0px -10% 0px",
      threshold: 0.1,
    },
  );

  targets.forEach((target) => observer.observe(target));

  return () => observer.disconnect();
}

document.addEventListener("DOMContentLoaded", () => {
  setupScrollReveal();
});

AstroやNext.jsでページ遷移後に再初期化が必要な場合は、ページのライフサイクルに合わせてsetupScrollReveal()を呼び直します。モーダルやタブ内に後から要素を追加する場合は、対象の親要素をrootとして渡すと、ページ全体を再走査せずに済みます。

ボタン反応の小さなJS例

ユーザー操作への反応は、スクロール演出より短くします。次の例は、クリック時にボタンを軽く縮め、完了後に状態テキストを更新します。Web Animations APIを使っていますが、reduce motionでは動かしません。

const button = document.querySelector("[data-save-button]");
const status = document.querySelector("[data-save-status]");

button?.addEventListener("click", async () => {
  const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
  button.setAttribute("aria-busy", "true");
  status.textContent = "保存しています...";

  if (!reduceMotion) {
    await button.animate(
      [
        { transform: "scale(1)" },
        { transform: "scale(0.97)" },
        { transform: "scale(1)" },
      ],
      { duration: 180, easing: "ease-out" },
    ).finished;
  }

  await new Promise((resolve) => window.setTimeout(resolve, 300));
  button.setAttribute("aria-busy", "false");
  status.textContent = "保存しました";
});

この例で大切なのは、動きがなくても状態が分かることです。status.textContentで文言を変え、aria-busyで処理中を伝えます。アニメーションは補助であり、唯一の情報源にしません。

落とし穴(よくある失敗と対策)

最初の落とし穴は、動きの目的が曖昧なまま実装することです。「おしゃれにする」ではレビューできません。「CTA直前のカードに気づいてもらう」「保存完了を伝える」「読み込み中の不安を減らす」のように、1文で説明できる目的にします。

2つ目は、アニメーション時間を長くしすぎることです。ページ表示時にすべてのカードが順番に1秒ずつ出ると、読者は本文へ進めません。特に検索流入の記事では、最初の3行とコード例へ早く到達できることが重要です。装飾的な動きは短く、操作結果は即時に返します。

3つ目は、スマホ幅の確認不足です。transform: translateX(40px)のような横方向の移動は、親要素の幅や影の描画と重なって横スクロールを作ることがあります。375px、414px、768pxの3幅で確認し、コードブロック、表、CTA、広告枠が重ならないか見ます。

4つ目は、色と動きだけで状態を伝えることです。赤く揺れるフォームだけでは、何が間違っているか分かりません。エラー文、aria-describedby、フォーカス移動、スクリーンリーダー向けの状態表示を合わせて実装します。

5つ目は、ライブラリを先に入れることです。GSAPやFramer Motionが必要な場面はありますが、記事カードのフェードイン、ボタンの軽い反応、トースト表示ならCSSと小さなJSで足ります。依存を増やす前に、初回表示、バンドルサイズ、保守担当を確認します。

6つ目は、Claude Codeの差分をそのまま受け入れることです。生成されたコードが動いても、既存の命名規則、デザイントークン、テスト、アクセシビリティ方針と合わなければ負債になります。必ず「変更ファイル」「追加したCSS変数」「削った代替案」「手動確認」を説明させます。

レビューと検証の手順

実装後は、Claude Codeへレビュー専用の依頼を出します。ここでは新しい機能追加を禁止し、問題点だけを洗い出させます。

今の差分をレビューしてください。新しい実装はしないでください。
1. アクセシビリティ上の問題
2. prefers-reduced-motionの漏れ
3. 375px幅で崩れそうな箇所
4. パフォーマンス上の懸念
5. 既存CSSやコンポーネントとの衝突
6. リリース前に人間が確認すべき操作
の順で、厳しめに指摘してください。

人間側の確認では、通常表示、reduce motion、キーボード操作、スマホ幅、低速回線、空データを見ます。ブラウザの開発者ツールでprefers-reduced-motionをエミュレートし、アニメーションが止まっても意味が通るか確認します。さらに、CTAが画面外へ押し出されていないか、/products//training/へのリンクが押しやすいか、記事内のコードブロックが横スクロールできるかも見ます。

収益導線としての考え方

UIアニメーションは、単体では売上を作りません。売上に効くのは、読者が迷わず次の行動へ進めることです。個人開発者なら、テンプレートやチェックリストを探している読者へ ClaudeCodeLab製品 を案内します。チームでClaude Codeを導入する読者には、権限、レビュー、CI、運用ルールまで含めて Claude Code研修・相談 へ誘導します。

記事や商品ページでのアニメーションは、この導線を補助する程度に留めます。CTAを常に揺らすより、セクションが見えたタイミングで一度だけ表示する方が上品で、読者の集中も切りません。Masaが既存記事ページで試した範囲では、派手なヒーロー演出より、記事末尾の関連カードとCTAを読みやすく整えた方が、修正範囲もレビュー時間も小さく済みました。

実際に試した結果

この記事の手順を、既存のブログUIに近い構成で試しました。Claude Codeには最初から全体リデザインを頼まず、data-revealを使うカード表示、prefers-reduced-motion対応、ボタンの短い反応だけを依頼しました。その後、レビュー専用プロンプトで375px幅、キーボード操作、空データ、CTAの見え方を確認させました。

結果として、1回の大きな依頼よりも、実装、レビュー、修正の3段階に分けた方が差分を読みやすく、落とし穴も早く見つかりました。特に横方向の移動を避け、opacitytransform: translateY()に限定したことで、スマホ幅の崩れが減りました。動きは小さくても、状態テキストとフォーカス表示を残すだけで、初心者にもレビューしやすい実装になります。

#Claude Code #animation #CSS #frontend #performance
無料

無料PDF: Claude Code はじめてのチートシート

まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。

スパムは送りません。登録情報は厳重に管理します。

Claude Codeを仕事で使える形にしませんか?

無料PDFで基礎を固めたあと、すぐ使えるテンプレート集で試し、必要なら業務自動化や導入相談まで進められます。

Masa

この記事を書いた人

Masa

Claude Codeの実務活用、導入設計、収益導線改善を検証しているエンジニア。10言語の技術メディアを運営中。

PR

関連書籍・参考図書

この記事のテーマに関連する書籍を楽天ブックスで探せます。

※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。