はじめに
正直なところ、LPやポートフォリオサイトを作るとき、アニメーションの実装には毎回悩まされていたんですよ。Framer Motionは強力だけど、一から書くのは面倒。かといって、既存のアニメーションライブラリは「それっぽい」けど微妙にダサい。
そんなときに出会ったのがMagic UI。GitHubで19,700スター以上を獲得していて、「デザインエンジニア向けのUIライブラリ」という触れ込み。実際に使ってみたら、これがかなり良かったんです。
30代になって思うのは、「見た目の良さ」と「実装の手軽さ」は両立できるということ。Magic UIはまさにその両立を実現してくれます。
Magic UIとは
Magic UIは、アニメーション付きのUIコンポーネントをコピー&ペーストで使えるライブラリです。公式サイトでは「UI Library for Design Engineers」と説明されています。
shadcn/uiと同じアプローチを採用していて、npmパッケージとしてインストールするのではなく、コンポーネントのソースコードを自分のプロジェクトに追加して使います。
特筆すべきは、アニメーションに特化しているという点。通常のButtonやCardではなく、Marquee(流れるテキスト)、Particles(パーティクル効果)、Globe(3D地球儀)といった、見栄えのするコンポーネントが揃っています。
- リポジトリ: magicuidesign/magicui
- スター数: 19,700以上
- ライセンス: MIT License
- コントリビューター: 129名以上
特徴・メリット
1. shadcn/ui互換のアーキテクチャ
これ、意外と重要なポイント。shadcn/uiを使っているプロジェクトなら、ほぼ同じ感覚で導入できます。
ディレクトリ構成もcomponents/ui/に配置する形式なので、既存のshadcn/uiコンポーネントと共存させやすい。技術スタックもTailwind CSS + Framer Motionで統一されています。
2. プロダクションレベルのアニメーション
個人的には、この品質が一番のメリットだと思います。
自分でアニメーションを一から作ると、どうしても「素人っぽさ」が出てしまう。イージングの調整とか、タイミングの微調整とか、地味に時間がかかるんですよね。
Magic UIのコンポーネントは、その辺りが最初から調整済み。コピペするだけで、プロが作ったようなモーションが手に入ります。
3. 50以上のコンポーネント
- テキスト系: Marquee、Typing Animation、Word Rotate、Text Reveal
- 背景系: Particles、Aurora Background、Dot Pattern、Grid Pattern
- インタラクション系: Ripple、Shine Border、Border Beam
- 3D系: Globe、Orbiting Circles
- UI系: Animated Card、Bento Grid、Dock
特にLPでよく使う「流れるロゴ一覧」とか「キラキラ光るボーダー」が簡単に実装できるのは時短になる。
4. TypeScriptで型安全
全コンポーネントがTypeScriptで書かれていて、propsの型定義もしっかりしている。補完が効くので、使い方を調べながら実装できます。
5. カスタマイズの自由度
ソースコードが手元にあるので、色やサイズ、アニメーションの速度など、自由にカスタマイズできます。気に入らない部分があれば、直接編集すればいい。
インストール方法
前提条件
- Node.js 18以降
- Reactプロジェクト(Next.js推奨)
- Tailwind CSS v3.4以上
- Framer Motion(アニメーションコンポーネントで使用)
CLIでの初期化
# npxの場合
npx magicui-cli init
# pnpmの場合
pnpm dlx magicui-cli init
このコマンドで、必要な設定ファイルとユーティリティがセットアップされます。
コンポーネントの追加
# Marqueeコンポーネントを追加
npx magicui-cli add marquee
# 複数まとめて追加
npx magicui-cli add marquee particles globe
# 特定のコンポーネントをチェック
npx magicui-cli add
追加されたコンポーネントはcomponents/magicui/ディレクトリに配置されます。
手動インストール
CLIを使わずに、公式サイトからコードをコピペすることも可能です。各コンポーネントのページに「Copy」ボタンがあるので、そこからコピーしてcomponents/magicui/に配置すればOK。
依存関係(Framer Motionなど)は別途インストールする必要があります。
npm install framer-motion clsx tailwind-merge
基本的な使い方
Marquee(流れるテキスト・ロゴ)
LPでよく見る、ロゴやテキストが横に流れるやつ。
import { Marquee } from "@/components/magicui/marquee";
const logos = [
{ name: "Google", src: "/logos/google.svg" },
{ name: "Microsoft", src: "/logos/microsoft.svg" },
{ name: "Amazon", src: "/logos/amazon.svg" },
{ name: "Meta", src: "/logos/meta.svg" },
];
export function ClientLogos() {
return (
<div className="relative flex w-full flex-col items-center justify-center overflow-hidden">
<Marquee pauseOnHover className="[--duration:20s]">
{logos.map((logo) => (
<img
key={logo.name}
src={logo.src}
alt={logo.name}
className="h-12 w-auto mx-8 grayscale hover:grayscale-0 transition-all"
/>
))}
</Marquee>
</div>
);
}
--durationというCSS変数で速度を調整できます。pauseOnHoverを付けると、ホバー時に止まる。
Particles(パーティクル背景)
ヒーローセクションの背景に使うと映えるやつ。
import { Particles } from "@/components/magicui/particles";
export function HeroSection() {
return (
<div className="relative min-h-screen flex items-center justify-center">
<Particles
className="absolute inset-0"
quantity={100}
ease={80}
color="#ffffff"
refresh
/>
<div className="relative z-10 text-center">
<h1 className="text-5xl font-bold">Welcome to My Site</h1>
<p className="mt-4 text-xl text-muted-foreground">
Something amazing is coming
</p>
</div>
</div>
);
}
Border Beam(光るボーダー)
カードやボタンの周りを光が走るエフェクト。
import { BorderBeam } from "@/components/magicui/border-beam";
export function FeatureCard() {
return (
<div className="relative rounded-xl border bg-background p-6">
<BorderBeam size={250} duration={12} delay={9} />
<h3 className="text-xl font-semibold">特別な機能</h3>
<p className="mt-2 text-muted-foreground">
この機能を使うと、作業効率が3倍になります。
</p>
</div>
);
}
Typing Animation(タイピングエフェクト)
テキストがタイプライターのように表示されるエフェクト。
import { TypingAnimation } from "@/components/magicui/typing-animation";
export function HeroTitle() {
return (
<TypingAnimation
className="text-4xl font-bold"
text="エンジニアの生産性を10倍にする"
duration={100}
/>
);
}
Shine Border(輝くボーダー)
ボタンやカードに使うと高級感が出る。
import { ShineBorder } from "@/components/magicui/shine-border";
export function CTAButton() {
return (
<ShineBorder
className="text-center text-lg font-medium"
color={["#A07CFE", "#FE8FB5", "#FFBE7B"]}
>
今すぐ始める
</ShineBorder>
);
}
実践的なユースケース
LPのヒーローセクション
複数のコンポーネントを組み合わせた実践例。
import { Particles } from "@/components/magicui/particles";
import { TypingAnimation } from "@/components/magicui/typing-animation";
import { ShineBorder } from "@/components/magicui/shine-border";
import { Button } from "@/components/ui/button";
export function LandingHero() {
return (
<section className="relative min-h-screen flex items-center justify-center bg-black">
{/* 背景パーティクル */}
<Particles
className="absolute inset-0"
quantity={80}
color="#ffffff"
ease={80}
/>
{/* コンテンツ */}
<div className="relative z-10 text-center text-white px-4">
<TypingAnimation
className="text-5xl md:text-7xl font-bold mb-6"
text="未来を、今ここに。"
duration={80}
/>
<p className="text-xl md:text-2xl text-gray-300 mb-8 max-w-2xl mx-auto">
革新的なテクノロジーで、あなたのビジネスを加速させます
</p>
<div className="flex gap-4 justify-center">
<ShineBorder
className="px-8 py-3 text-lg font-semibold"
color={["#6366f1", "#8b5cf6", "#d946ef"]}
>
無料で試す
</ShineBorder>
<Button variant="outline" size="lg" className="text-white border-white hover:bg-white/10">
詳しく見る
</Button>
</div>
</div>
</section>
);
}
クライアント一覧セクション
import { Marquee } from "@/components/magicui/marquee";
const clients = [
{ name: "TechCorp", logo: "/clients/techcorp.svg" },
{ name: "StartupX", logo: "/clients/startupx.svg" },
{ name: "Enterprise Inc", logo: "/clients/enterprise.svg" },
// ... more clients
];
export function ClientsSection() {
return (
<section className="py-16 bg-muted/50">
<div className="container mx-auto px-4">
<h2 className="text-center text-sm font-semibold text-muted-foreground mb-8">
多くの企業に選ばれています
</h2>
<Marquee pauseOnHover className="[--duration:30s]">
{clients.map((client) => (
<div key={client.name} className="mx-8">
<img
src={client.logo}
alt={client.name}
className="h-8 w-auto opacity-50 hover:opacity-100 transition-opacity"
/>
</div>
))}
</Marquee>
</div>
</section>
);
}
機能紹介カード
import { BorderBeam } from "@/components/magicui/border-beam";
import { MagicCard } from "@/components/magicui/magic-card";
const features = [
{
title: "高速処理",
description: "最新の技術で、従来の10倍の速度を実現",
icon: "⚡",
},
{
title: "セキュリティ",
description: "エンタープライズグレードのセキュリティ",
icon: "🔒",
},
{
title: "スケーラブル",
description: "成長に合わせて柔軟に拡張可能",
icon: "📈",
},
];
export function FeaturesSection() {
return (
<section className="py-20">
<div className="container mx-auto px-4">
<h2 className="text-3xl font-bold text-center mb-12">
選ばれる3つの理由
</h2>
<div className="grid md:grid-cols-3 gap-8">
{features.map((feature, index) => (
<div
key={feature.title}
className="relative rounded-xl border bg-background p-8"
>
<BorderBeam size={200} duration={15} delay={index * 3} />
<div className="text-4xl mb-4">{feature.icon}</div>
<h3 className="text-xl font-semibold mb-2">{feature.title}</h3>
<p className="text-muted-foreground">{feature.description}</p>
</div>
))}
</div>
</div>
</section>
);
}
shadcn/uiとの使い分け
個人的には、こう使い分けています。
| 用途 | 使うライブラリ |
|---|---|
| フォーム、ダイアログ、テーブル | shadcn/ui |
| ヒーローセクション、背景効果 | Magic UI |
| ボタン、カード(静的) | shadcn/ui |
| ボタン、カード(装飾的) | Magic UI |
| 管理画面のUI | shadcn/ui |
| LP、ポートフォリオ | Magic UI |
コスパ的に、両方入れておいて使い分けるのがベスト。競合しないので共存できます。
注意点
パフォーマンス
アニメーションは見栄えがする一方で、パフォーマンスへの影響もあります。特にParticlesやGlobeは描画負荷が高いので、モバイル端末では控えめに使った方がいい。
// モバイルでは軽量版にする例
const isMobile = typeof window !== "undefined" && window.innerWidth < 768;
<Particles quantity={isMobile ? 30 : 100} />
アクセシビリティ
アニメーションが苦手な人もいるので、prefers-reduced-motionへの対応は忘れずに。Magic UIのコンポーネントは基本的に対応していますが、カスタマイズ時は注意。
まとめ
Magic UIを導入して感じた変化:
- LP制作の時短: アニメーション実装にかける時間が大幅に減った
- クオリティ向上: プロっぽいモーションが簡単に実現できる
- 学習コスト低: shadcn/uiと同じ感覚で使える
- 自由度: ソースが手元にあるのでカスタマイズし放題
30代になって思うのは、「自分で一から作る」ことに価値があるわけではないということ。良いものは借りて、自分はビジネスロジックに集中する。Magic UIはその考え方にぴったりのライブラリです。
特にLP制作やポートフォリオサイトを作る機会がある人には、かなりおすすめ。shadcn/uiと併用すれば、見た目も機能も妥協しないサイトが作れますよ。