Claude CodeでCSSアニメーション上級実装:速く、酔わせず、壊さない設計
Claude CodeでCSSアニメーションを実装する実践ガイド。性能、アクセシビリティ、検証まで解説。
CSSアニメーションは「動けばよい」では足りない
Claude Codeに「このカードをふわっと表示して」と頼むと、CSSはすぐ生成されます。ただし本番UIで大事なのは、派手な動きではなく、読みやすさ、速度、保守性、そして動きを苦手に感じる人への配慮です。アニメーションは装飾ではなく、ユーザーに「何が変わったか」を伝えるための状態表現です。
この記事では、Claude Codeで高度なCSSアニメーションを作るときの実装手順を、初心者にも読めるように整理します。扱う範囲は、transitionとkeyframesの使い分け、transformとopacity中心の高速な動き、layout thrash、prefers-reduced-motion、スクロール連動と入口アニメーション、スケルトン表示、デザインシステムのトークン、Playwrightによる見た目チェック、そして「動かさない判断」です。
用語も最初に噛み砕きます。transitionは「ボタンの色が変わる」ような開始値と終了値だけの小さな変化です。keyframesは「0%、60%、100%」のように途中経過まで指定するタイムラインです。layout thrashは、JavaScriptやCSSの変更でブラウザが何度もレイアウト計算をやり直す状態です。トークンは、--motion-duration-fast のように名前を付けて管理する設計値です。
内部の関連テーマとして、全体速度の考え方はClaude Codeパフォーマンス最適化、変数管理はClaude CodeでCSS変数を使う設計、配慮の観点はClaude Codeアクセシビリティ実装も合わせて読むとつながります。
transitionとkeyframesを使い分ける
transitionは、ユーザー操作に反応する短い変化に向いています。hover、focus、開閉、選択状態の切り替えなどです。keyframesは、ローディング、入口アニメーション、段階的な注意喚起など、途中の動きを設計したい場面に向いています。
Claude Codeへの依頼では、最初に「どちらを使うか」を指定すると品質が安定します。曖昧に「いい感じに動かして」と書くと、top、left、heightをアニメーションさせるコードが混ざることがあります。これらはレイアウト再計算を起こしやすく、画面がカクつく原因になります。
:root {
--motion-duration-fast: 160ms;
--motion-duration-normal: 280ms;
--motion-ease-standard: cubic-bezier(0.2, 0, 0, 1);
--motion-distance-sm: 12px;
}
.button {
transition:
background-color var(--motion-duration-fast) var(--motion-ease-standard),
transform var(--motion-duration-fast) var(--motion-ease-standard);
}
.button:hover {
transform: translateY(-2px);
}
.notice {
opacity: 0;
transform: translateY(var(--motion-distance-sm));
animation: notice-enter var(--motion-duration-normal) var(--motion-ease-standard) forwards;
}
@keyframes notice-enter {
from {
opacity: 0;
transform: translateY(var(--motion-distance-sm));
}
to {
opacity: 1;
transform: translateY(0);
}
}
この例では、ボタンのhoverはtransition、通知の表示はkeyframesに分けています。background-colorは小さなUIなら問題になりにくいですが、移動や拡大縮小はtransformで行います。MDNのCSS animationsとtransformは、仕様確認の一次情報として便利です。
速いアニメーションはtransformとopacityから作る
ブラウザは画面を作るとき、レイアウト、ペイント、合成という流れで処理します。ざっくり言うと、レイアウトは要素の大きさや位置を計算する工程、ペイントは色や影を描く工程、合成は描いたレイヤーを重ねる工程です。transformとopacityは合成で処理しやすく、比較的安定して動きます。
逆に、width、height、margin、top、leftを頻繁に動かすと、周囲の要素の位置まで再計算されることがあります。これがlayout thrashの典型です。Claude Codeには「移動はtransform、表示非表示はopacity、開閉で高さが必要な場合はアクセシブルな代替も検討」と明示します。
import type { ReactNode } from "react";
import "./motion.css";
type AnimatedPanelProps = {
children: ReactNode;
isOpen: boolean;
};
export function AnimatedPanel({ children, isOpen }: AnimatedPanelProps) {
return (
<section
className={isOpen ? "panel panel-enter" : "panel"}
aria-hidden={!isOpen}
>
{children}
</section>
);
}
.panel {
opacity: 0;
transform: translateY(12px) scale(0.98);
pointer-events: none;
}
.panel-enter {
animation: panel-enter 220ms cubic-bezier(0.2, 0, 0, 1) forwards;
pointer-events: auto;
}
@keyframes panel-enter {
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
will-changeは万能薬ではありません。アニメーション直前に限定して使うなら効果がありますが、常時付けるとメモリを余計に使います。web.devのanimation performance guideでも、動かすプロパティの選択が重要だと説明されています。
実用ユースケース:入口、スクロール、ローディング
1つ目のユースケースは、記事カードや料金表の入口アニメーションです。ページを開いた瞬間に全要素が同時に出るより、主要コンテンツだけを短く表示させると視線を誘導できます。ただし、全カードに大きな遅延を付けると読者を待たせるだけです。遅延は80ms程度を上限にし、本文の読書を邪魔しない範囲にします。
2つ目は、スクロール連動の進捗バーやセクション表示です。CSSのanimation-timelineは魅力的ですが、対応状況を確認し、未対応ブラウザでも読める状態を残します。スクロールでしか情報が出ない設計は避け、アニメーションが無効でも内容が見えるようにします。
.scroll-progress {
position: fixed;
inset: 0 auto auto 0;
z-index: 20;
width: 100%;
height: 3px;
transform-origin: left;
transform: scaleX(0);
background: var(--color-accent, #2563eb);
}
@supports (animation-timeline: scroll()) {
.scroll-progress {
animation: progress-grow linear both;
animation-timeline: scroll();
}
}
@keyframes progress-grow {
to {
transform: scaleX(1);
}
}
.reveal {
opacity: 1;
transform: none;
}
@supports (animation-timeline: view()) {
.reveal {
opacity: 0;
transform: translateY(16px);
animation: reveal-up 1ms linear both;
animation-timeline: view();
animation-range: entry 10% cover 30%;
}
}
@keyframes reveal-up {
to {
opacity: 1;
transform: translateY(0);
}
}
3つ目は、スケルトン表示やローディング状態です。スケルトンは「読み込み中の形」を示すUIで、空白より不安を減らせます。ただし、波のような強い shimmer を長時間ループさせると疲れます。数秒以上続く処理では、進捗テキストやキャンセル導線を用意します。
4つ目は、ダッシュボードの状態変化です。フィルタ変更、保存完了、エラー表示は、短い動きで変化を伝えると認知負荷が下がります。一方で、売上数値やログ一覧のように何度も見る画面では、毎回派手に動くUIは作業効率を落とします。業務画面では「控えめ」を基準にします。
reduced motionと「動かさない判断」
prefers-reduced-motionは、ユーザーがOSやブラウザで「動きを減らしたい」と設定しているかをCSSで読む機能です。めまい、集中の妨げ、疲労を避けるために重要です。MDNのprefers-reduced-motionに仕様と例があります。
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
scroll-behavior: auto !important;
animation-duration: 1ms !important;
animation-delay: 0ms !important;
animation-iteration-count: 1 !important;
transition-duration: 1ms !important;
}
.scroll-progress {
animation: none;
transform: scaleX(1);
}
.skeleton {
animation: none;
background-image: none;
}
}
動かさないほうがよい場面もあります。入力フォームのエラー文、決済画面、法的な注意、長い本文、管理画面の表、ユーザーが何度も開くメニューでは、動きよりも即時性と安定性を優先します。アニメーションは「意味がある変化」にだけ使うと、結果的にプロダクト全体が上品になります。
Claude Codeに渡す実装プロンプト
Claude Codeには、見た目だけでなく制約を渡します。次のプロンプトは、そのままレビュー依頼にも使えます。
Review and improve the CSS animation implementation for this UI.
Requirements:
- Use transition for simple hover/focus/open states.
- Use keyframes only when intermediate timing matters.
- Animate transform and opacity first; avoid top, left, width, height, and margin animations.
- Add design tokens for duration, easing, and distance.
- Respect prefers-reduced-motion.
- Keep content visible when scroll-linked animation is unsupported.
- Do not animate critical form errors, payment confirmation, or long reading content.
Return:
1. Risky selectors and why they are risky.
2. A corrected CSS/React implementation.
3. Manual and Playwright checks to verify overflow and reduced motion.
ポイントは、Claude Codeに「何を作るか」だけでなく「何を避けるか」を伝えることです。特にlayout thrash、無限ループ、will-changeの付けっぱなし、モーション設定無視は、生成コードで見落としやすい落とし穴です。
Playwrightで見た目と設定を検証する
最後に、自動チェックを入れます。アニメーションは単体テストだけでは壊れ方を拾いにくいので、Playwrightで横スクロール、入口要素の表示、reduced motion時の状態を確認します。
import { expect, test } from "@playwright/test";
test("animated page has no horizontal overflow", async ({ page }) => {
await page.goto("/animation-demo");
const overflow = await page.evaluate(() => {
return document.documentElement.scrollWidth > window.innerWidth;
});
expect(overflow).toBe(false);
});
test("reduced motion keeps content visible", async ({ browser }) => {
const context = await browser.newContext({ reducedMotion: "reduce" });
const page = await context.newPage();
await page.goto("/animation-demo");
await expect(page.locator(".reveal").first()).toBeVisible();
await expect(page.locator(".skeleton").first()).toHaveCSS("animation-name", "none");
await context.close();
});
実務では、ここにスクリーンショット比較も加えます。Playwrightのチェックは「完璧なデザイン判断」ではありませんが、横スクロール、非表示のまま残る要素、reduced motion無視のような公開事故を早めに見つけられます。
まとめと次の一手
Claude CodeでCSSアニメーションを作るときは、最初に役割を決めます。小さな状態変化はtransition、時間軸を設計する動きはkeyframes。移動と表示はtransformとopacityを中心にし、layout thrashを避けます。さらに、prefers-reduced-motion、スクロール未対応時のフォールバック、デザイントークン、Playwright確認まで含めると、本番で使える品質になります。
次に試すなら、既存のカード一覧やCTAボタンを1つ選び、この記事のトークン、入口アニメーション、reduced motion、Playwrightチェックを小さく入れてください。Claude Codeの依頼文を型として残したい場合は、トレーニングと相談から実装レビューの流れを確認できます。
この記事で紹介した内容を実際に試した結果、transformとopacityに限定した入口アニメーションは横スクロールを起こさず、reduced motionを有効にしたPlaywright実行でも本文が表示されたままになりました。一方で、スケルトンの shimmer は強すぎると読み込みが長く感じられたため、業務画面では静的なプレースホルダーに寄せる判断が現実的でした。
無料PDF: Claude Code はじめてのチートシート
まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。
スパムは送りません。登録情報は厳重に管理します。
Claude Codeを仕事で使える形にしませんか?
無料PDFで基礎を固めたあと、すぐ使えるテンプレート集で試し、必要なら業務自動化や導入相談まで進められます。
この記事を書いた人
Masa
Claude Codeの実務活用、導入設計、収益導線改善を検証しているエンジニア。10言語の技術メディアを運営中。
関連書籍・参考図書
この記事のテーマに関連する書籍を楽天ブックスで探せます。
※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。
関連記事
Claude Code Permission Receipt Pattern: 許可、証拠、ロールバックを残す運用
Claude Codeの権限運用を安全にする permission receipt。許可範囲、承認待ち、検証コマンド、CTA導線を記録します。
Claude CodeとCodex、結局どっち?事故らない“併用”の現実解
OpenAIのCodexとClaude Code、どっちが得意でどっちに任せる?両方を安全に併用する作業分担と権限・検証のワークフローを、僕の失敗談つきで解説します。
Claude Codeサブエージェント実装ガイド: 記事・コード作業を安全に並列委譲する方法
Claude Codeサブエージェントで記事・コード作業を安全に並列化する実装ガイド。委譲基準、プロンプト、失敗例を解説。