ui-enhance-animate について
既存のウェブサイトやコンポーネントを幅広く改善するUI設計スキルです。元のカラーパレットを維持しながら、タイポグラフィ、レイアウト、余白、インタラクションを整え、段階的な表示アニメーションを加えます。
主な機能
- 01既存の色とコンポーネントの確認
- 02文字組み、余白、レイアウトの改善
- 03カードの奥行きと操作状態の調整
- 04段階的なぼかし・スライド表示
- 05視差効果の低減設定への対応
活用シーン
- 01既存サイトの視覚的な階層を改善
- 02ページ各部にスクロール表示効果を追加
- 03カード、ボタン、ナビゲーションのスタイル調整
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ zaaakher/ agent-skills --skill ui-enhance-animateインストール後、Claude Code で/ui-enhance-animateを入力して読み込まれたか確認します。
詳細
UI 強化+段階的アニメーションスキル
このスキルは、既存のウェブサイトやコンポーネントを全面的にデザインアップグレードします。アニメーションを追加するだけではありません。タイポグラフィ、余白、レイアウト、奥行き、マイクロインタラクション、動きにわたる、包括的なビジュアル改善を行います。既存のカラーパレットは維持し、それ以外はすべて改善できますし、改善すべきです。
フェーズ 1 — 変更を始める前に監査して把握する
コードを 1 行でも書く前に、既存のコードを徹底的に読み込みます。次の項目を抽出して記録してください。
- カラーパレット — すべての hex/hsl/rgb 値、CSS 変数、Tailwind のカラークラス。これらは必ず正確に維持する必要があります。
- フォントスタック — 現在使用されているフォント。
- レイアウト構造 — CSS Grid、Flexbox、通常のブロックのどれか。ページ全体はどのような構造か。
- コンポーネント一覧 — ヒーロー、ナビゲーションバー、カード、機能紹介、お客様の声、CTA、フッターなど、各セクション/コンポーネントを列挙します。
- 現在の弱点 — 素人っぽく、あるいはありきたりに見える点を視覚的に特定します。平坦なカード、余白のリズムがない、タイポグラフィの階層が弱い、奥行きやシャドウがない、ありきたりなホバー状態、視覚的な流れがない、テキストが詰め込まれている、といった点です。
- 技術スタック — React(Framer Motion を使用)、プレーンな HTML/CSS(CSS アニメーション+IntersectionObserver を使用)、Vue など。
この監査を終えてから、変更を始めてください。
フェーズ 2 — 全面的なデザインアップグレード(アニメーション以外)
サイトに関連する以下の改善をすべて適用します。徹底的に行い、「問題なさそう」に見えるセクションを飛ばさないでください。サイトのすべての部分を洗練させます。
タイポグラフィ
- 明確なタイポグラフィの階層を導入します。ディスプレイサイズ(clamp ベースの流体的なサイズ設定)、セクション見出し、小見出し、本文、キャプションを、それぞれ異なるウェイトとサイズで設定します。
- ありきたりなシステムフォント(Arial、Helvetica、system-ui)を、Google Fonts などから選んだ個性のあるフォントの組み合わせに置き換えます。存在感のあるディスプレイ/見出し用フォントと、読みやすい本文用フォントを組み合わせます。
- 大文字のラベルやオーバーラインには
letter-spacingを使用します。 line-heightにリズムを持たせます。見出しは約 1.2、本文は約 1.6~1.7 にします。- 読みやすさを高めるため、長いテキストブロックには
max-width: 65chを設定します。
余白とリズム
- 一貫した余白のスケール(例:4/8/16/24/32/48/64/96px)を導入します。
- セクションのパディングを増やします。素人っぽいサイトの多くは余白が詰まりすぎています。
- セクション内の各コンポーネント間に、十分な余白を設けます。
- カードやコンポーネント内部のパディングを統一します。
奥行きと表面表現
- カード、モーダル、浮き上がったサーフェスに、複数層の
box-shadowを追加します。強く単層のシャドウではなく、柔らかなシャドウを重ねて使います。 - 輪郭を強く描く代わりに、低い不透明度の色で控えめな
borderを設定します。 - 適切な場合は、ナビゲーションバーや重なり合うカードなど、グラスモーフィズムを使った要素に
backdrop-filter: blur()を適用します。 - 既存の色をわずかに明るく、または暗くした色合いで、セクション間に控えめな
backgroundの変化をつけます。
レイアウトと構成
- 画一的なグリッドレイアウトだけにせず、効果的な箇所には非対称やオフセットの構成を取り入れます。
- 既存のカラーパレットを使い、不透明度を低くした装飾要素、大きな背景テキストや数字、グラデーションのぼかし、幾何学図形などの視覚的なアンカーを追加します。
- 十分なサイズ感と明確な焦点を持たせ、ヒーローを印象的に仕上げます。
- 複雑なレイアウトには CSS Grid を使用し、ネストした div を過剰に使わないようにします。
カードとコンポーネント
- すべての角丸を一貫させます(カードは通常 8~16px、ボタンや入力欄は 6~8px)。
- すべてのインタラクティブ要素にホバー状態を追加します。カードは浮き上がるようにし(translateY+シャドウ)、ボタンは移動または発光させます。
- ボタンには視認しやすいパディングと十分なコントラストを持たせ、控えめなアイコンや矢印の追加も検討します。
- インタラクティブ要素には、基本として
transition: all 0.2s easeを追加します。
ビジュアルの仕上げに関する詳細
- ヒーロー画像や暗いセクションに、控えめなグラデーションオーバーレイを追加します。
- カードに
overflow: hiddenを設定し、子要素の画像やエフェクトをきれいに切り取ります。 - 画像には
object-fit: coverを設定し、アスペクト比を明示します。 - セクション間に区切りの装飾(控えめな境界線、グラデーションのフェード、装飾的な波形や角度)を追加します。
- アイコンがある場合は、サイズを統一し、テキストと視覚的に揃えます。
フェーズ 3 — ぼかしとスライドアップを組み合わせた段階的な表示アニメーション
アニメーションの方針
- アニメーションは、派手さや注意をそらすことなく、自然で優雅に感じられるようにします。
- 主要なコンテンツセクションすべてで、ビューポートに入ったときにアニメーションを実行します。
- 段階的なパターンを使用します。セクション内の子要素を、遅延時間をずらしながら(例:0.1 秒ずつ)1 つずつ表示します。
- アニメーションでは、要素の開始状態を
opacity: 0、filter: blur(8px)、translateY(24px)とし、終了状態をopacity: 1、filter: blur(0px)、translateY(0)とします。 - 時間:ほとんどの要素で 0.6 秒。イージング:
ease-outまたはcubic-bezier(0.16, 1, 0.3, 1)のようなカスタムの cubic-bezier(軽快なスプリング)。 prefers-reduced-motionを尊重し、アニメーションを無効にする設定を選んだユーザーにはアニメーションを無効にします。
React — Framer Motion による実装
まだインストールされていない場合は、インストールします。
npm install framer-motion
基本のアニメーションバリアント
// lib/animations.ts
import { Variants } from "framer-motion";
export const fadeUpBlur: Variants = {
hidden: {
opacity: 0,
y: 24,
filter: "blur(8px)",
},
visible: {
opacity: 1,
y: 0,
filter: "blur(0px)",
transition: {
duration: 0.6,
ease: [0.16, 1, 0.3, 1],
},
},
};
export const staggerContainer: Variants = {
hidden: {},
visible: {
transition: {
staggerChildren: 0.1,
delayChildren: 0.05,
},
},
};
// For heavier stagger (e.g., feature grids)
export const staggerContainerSlow: Variants = {
hidden: {},
visible: {
transition: {
staggerChildren: 0.15,
delayChildren: 0.1,
},
},
};
再利用可能な AnimateInView ラッパー
// components/AnimateInView.tsx
import { motion, useInView } from "framer-motion";
import { useRef } from "react";
import { staggerContainer, fadeUpBlur } from "@/lib/animations";
interface AnimateInViewProps {
children: React.ReactNode;
className?: string;
delay?: number;
stagger?: boolean;
}
export function AnimateInView({
children,
className,
delay = 0,
stagger = false,
}: AnimateInViewProps) {
const ref = useRef(null);
const isInView = useInView(ref, { once: true, margin: "-80px" });
if (stagger) {
return (
<motion.div
ref={ref}
className={className}
variants={staggerContainer}
initial="hidden"
animate={isInView ? "visible" : "hidden"}
>
{children}
</motion.div>
);
}
return (
<motion.div
ref={ref}
className={className}
variants={fadeUpBlur}
initial="hidden"
animate={isInView ? "visible" : "hidden"}
transition={{ delay }}
>
{children}
</motion.div>
);
}
// Individual animated child (use inside AnimateInView with stagger=true)
export function AnimatedItem({
children,
className,
}: {
children: React.ReactNode;
className?: string;
}) {
return (
<motion.div className={className} variants={fadeUpBlur}>
{children}
</motion.div>
);
}
使用パターン
// Hero section — single block fade
<AnimateInView>
<h1>Your Headline</h1>
<p>Subheadline text here</p>
<Button>CTA</Button>
</AnimateInView>
// Feature grid — staggered children
<AnimateInView stagger className="grid grid-cols-3 gap-6">
{features.map((f) => (
<AnimatedItem key={f.id}>
<FeatureCard {...f} />
</AnimatedItem>
))}
</AnimateInView>
// Section heading + body — slight delays
<div>
<AnimateInView delay={0}>
<h2>Section Title</h2>
</AnimateInView>
<AnimateInView delay={0.1}>
<p>Section description</p>
</AnimateInView>
</div>
モーションの軽減
// Wrap your app or layout:
import { LazyMotion, domAnimation, MotionConfig } from "framer-motion";
export function Providers({ children }: { children: React.ReactNode }) {
return (
<MotionConfig reducedMotion="user">
<LazyMotion features={domAnimation}>
{children}
</LazyMotion>
</MotionConfig>
);
}
プレーンな HTML/CSS/JS — CSS と IntersectionObserver による実装
CSS アニメーションクラス
/* Add to your global stylesheet */
@media (prefers-reduced-motion: no-preference) {
.reveal {
opacity: 0;
transform: translateY(24px);
filter: blur(8px);
transition:
opacity 0.6s cubic-bezier(0.16, 1, 0.3, 1),
transform 0.6s cubic-bezier(0.16, 1, 0.3, 1),
filter 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}
.reveal.in-view {
opacity: 1;
transform: translateY(0);
filter: blur(0px);
}
/* Stagger delays for children */
.stagger-children .reveal:nth-child(1) { transition-delay: 0.0s; }
.stagger-children .reveal:nth-child(2) { transition-delay: 0.1s; }
.stagger-children .reveal:nth-child(3) { transition-delay: 0.2s; }
.stagger-children .reveal:nth-child(4) { transition-delay: 0.3s; }
.stagger-children .reveal:nth-child(5) { transition-delay: 0.4s; }
.stagger-children .reveal:nth-child(6) { transition-delay: 0.5s; }
/* Add more as needed */
}
IntersectionObserver スクリプト
// Add before closing </body>
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add("in-view");
observer.unobserve(entry.target); // animate once
}
});
},
{ rootMargin: "-80px 0px", threshold: 0.1 }
);
document.querySelectorAll(".reveal").forEach((el) => observer.observe(el));
使用パターン
<section>
<div class="reveal">
<h2>Section Title</h2>
<p>Description text</p>
</div>
</section>
<div class="stagger-children grid">
<div class="reveal card">Feature 1</div>
<div class="reveal card">Feature 2</div>
<div class="reveal card">Feature 3</div>
</div>
フェーズ 4 — セクションごとの適用ガイド
以下のように、各セクションの種類に応じて改善とアニメーションを適用します。
| セクション | デザインの改善 | アニメーションパターン |
|---|---|---|
| ナビゲーションバー | ガラスモーフィズムの backdrop-blur、控えめな下辺の境界線、ロゴ周りの余白を調整 | 読み込み時にフェードイン(スクロールはトリガーにしない) |
| ヒーロー | 大きく流動的な文字、明確な階層、グラデーションまたは装飾的なブロブ、CTA ボタンの仕上げ | 1 つのブロックを段階的に表示:見出し → 補足テキスト → CTA ボタン(各 0.1 秒) |
| 特徴/グリッド | カードに奥行きを追加(シャドウ+ホバー時の浮き上がり)、アイコンを調整、余白を統一 | グリッド項目を 0.1〜0.15 秒ずつずらして表示 |
| お客様の声 | 引用のスタイル、アバターの仕上げ、カードの表面を差別化 | カードを左から右へ段階的に表示 |
| 統計/数値 | アクセントカラーを使った大きな数値、ラベルのタイポグラフィ、区切り線 | 各統計情報を遅延時間をずらしてフェードイン |
| CTA セクション | 背景を効果的に仕上げ、ボタンを調整し、十分な余白を確保 | 1 つのブロックを表示 |
| フッター | カラム間の余白、リンクのホバー状態、控えめな区切り線 | 1 回の表示 |
フェーズ 5 — 品質チェックリスト
結果を納品する前に、以下を確認します。
- 元の色がすべて維持されている(新しいカラーパレットの色を追加していない)
- すべてのセクションに、少なくとも 1 つの
.reveal/AnimateInViewラッパーがある - 2 項目以上のすべてのグリッド/リスト/カードグループに段階的な表示が適用されている
-
prefers-reduced-motionが尊重されている - すべてのインタラクティブ要素にホバー状態がある
- タイポグラフィに明確な階層がある(すべて同じサイズ/太さではない)
- カード/サーフェスに奥行きがある(シャドウ、境界線、または背景による差別化)
- 余白にゆとりとリズムがあり、窮屈でない
- 汎用的な改善にとどまらず、すべての変更に意図があり、目に見える効果がある
- サイトが以前より明らかに洗練されている
補足とエッジケース
- サイトで Tailwind を使用している場合:Framer Motion の
motion.divを Tailwind クラスと組み合わせて使用します。ぼかしには任意の値[filter:blur(8px)]またはアニメーションの初期状態にインラインスタイルを指定します。 - 色が Tailwind の設定値として定義されている場合:アニメーションコンポーネントで参照しますが、変更しないでください。
- 画像がある場合:高さまたはアスペクト比を定義し、
object-fit: coverを指定してください。ホバー時に控えめな拡大を加えることも検討してください。 - ダークテーマのサイトの場合:グラスモーフィズムが特に効果的です。カードの背景には
bg-white/5など、透明度の低い白を使用します。 - ライトテーマのサイトの場合:柔らかく重ねたシャドウ(
shadow-smとshadow-mdの組み合わせ)を使用します。セクションを区別するために、背景にわずかな色味を加えます。 - パフォーマンス:
blur()フィルターのアニメーションは、ローエンドデバイスでは GPU に大きな負荷をかけることがあります。パフォーマンスが懸念される場合は、ぼかしをなくし、opacityとtranslateYのみを使用します。
コメント
Markdown 対応