tailwind-styling について
tailwind-stylingは、Tailwind CSSでReactコンポーネントをスタイリングするためのガイダンススキルです。ユーティリティクラス、レスポンシブレイアウト、ダークモード、再利用可能なコンポーネント、CSSのパフォーマンス対策を扱います。
主な機能
- 01ユーティリティファーストのReactスタイルパターン
- 02モバイルファーストのレスポンシブレイアウト
- 03ボタン、カード、フォームのコンポーネントパターン
- 04ダークモードの設定と実装
- 05JITと未使用CSS削減の指針
活用シーン
- 01React画面のレスポンシブスタイル作成
- 02再利用可能なコンポーネントパターンの構築
- 03Reactプロジェクトへのダークモード追加
- 04Tailwind CSSのパフォーマンス対策の確認
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ majesticlabs-dev/ majestic-marketplace --skill tailwind-stylingインストール後、Claude Code で/tailwind-stylingを入力して読み込まれたか確認します。
詳細
React 向け Tailwind CSS
概要
このスキルでは、ユーティリティクラス、レスポンシブデザイン、パフォーマンスに関するベストプラクティスを使用して、Tailwind CSS で React コンポーネントをスタイリングする方法を説明します。
基本理念
- ユーティリティファースト:ユーティリティクラスを組み合わせてデザインを構築します
- デフォルトでレスポンシブ:モバイルファーストのブレークポイントシステムを使用します
- コンポーネントの抽出:パターンを再利用可能なコンポーネントとして抽出します
- パフォーマンス:JIT モードを使用してバンドルサイズを最小限に抑えます
よく使用されるコンポーネントパターン
ボタンのバリエーション
interface ButtonProps {
children: ReactNode;
variant?: 'primary' | 'secondary' | 'danger';
size?: 'sm' | 'md' | 'lg';
onClick?: () => void;
}
export const Button: FC<ButtonProps> = ({
children,
variant = 'primary',
size = 'md',
onClick
}) => {
const baseClasses = 'font-medium rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2';
const variantClasses = {
primary: 'bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500',
secondary: 'bg-white text-gray-700 border border-gray-300 hover:bg-gray-50 focus:ring-blue-500',
danger: 'bg-red-600 text-white hover:bg-red-700 focus:ring-red-500'
};
const sizeClasses = {
sm: 'px-3 py-1.5 text-sm',
md: 'px-4 py-2 text-base',
lg: 'px-6 py-3 text-lg'
};
return (
<button
onClick={onClick}
className={`${baseClasses} ${variantClasses[variant]} ${sizeClasses[size]}`}
>
{children}
</button>
);
};
カードコンポーネント
export const Card: FC<{ title: string; children: ReactNode; footer?: ReactNode }> = ({
title,
children,
footer
}) => {
return (
<div className="bg-white shadow rounded-lg overflow-hidden">
<div className="px-6 py-4 border-b border-gray-200">
<h3 className="text-lg font-medium text-gray-900">{title}</h3>
</div>
<div className="px-6 py-4">{children}</div>
{footer && (
<div className="px-6 py-4 bg-gray-50 border-t border-gray-200">
{footer}
</div>
)}
</div>
);
};
フォーム入力
interface InputProps {
label: string;
error?: string;
type?: string;
value: string;
onChange: (value: string) => void;
}
export const Input: FC<InputProps> = ({ label, error, type = 'text', value, onChange }) => {
return (
<div className="space-y-1">
<label className="block text-sm font-medium text-gray-700">{label}</label>
<input
type={type}
value={value}
onChange={(e) => onChange(e.target.value)}
className={`
block w-full rounded-md shadow-sm sm:text-sm
${error
? 'border-red-300 text-red-900 placeholder-red-300 focus:border-red-500 focus:ring-red-500'
: 'border-gray-300 focus:border-blue-500 focus:ring-blue-500'
}
`}
/>
{error && <p className="text-sm text-red-600">{error}</p>}
</div>
);
};
レイアウトパターン
コンテナ
export const Container: FC<{ children: ReactNode }> = ({ children }) => {
return (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
{children}
</div>
);
};
グリッド
export const ProductGrid: FC<{ products: Product[] }> = ({ products }) => {
return (
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
{products.map(product => (
<ProductCard key={product.id} product={product} />
))}
</div>
);
};
Flexbox レイアウト
// Sidebar layout
export const SidebarLayout: FC<{ sidebar: ReactNode; children: ReactNode }> = ({
sidebar,
children
}) => {
return (
<div className="flex flex-col md:flex-row gap-6">
<aside className="w-full md:w-64 flex-shrink-0">
{sidebar}
</aside>
<main className="flex-1">
{children}
</main>
</div>
);
};
レスポンシブデザイン
ブレークポイント
sm:- 640pxmd:- 768pxlg:- 1024pxxl:- 1280px2xl:- 1536px
モバイルファーストパターン
<div className="
text-base /* Mobile */
sm:text-lg /* Tablet */
lg:text-xl /* Desktop */
xl:text-2xl /* Large screens */
">
Responsive text
</div>
<div className="
grid grid-cols-1 /* Mobile: 1 column */
sm:grid-cols-2 /* Tablet: 2 columns */
lg:grid-cols-3 /* Desktop: 3 columns */
gap-4
">
{/* Grid items */}
</div>
画面サイズに応じた表示/非表示
<div className="block md:hidden">Mobile only</div>
<div className="hidden md:block">Desktop only</div>
ダークモード
設定
// tailwind.config.js
module.exports = {
darkMode: 'class', // or 'media'
// ...
};
実装
export const ThemeToggle = () => {
const [dark, setDark] = useState(false);
useEffect(() => {
if (dark) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
}, [dark]);
return (
<button onClick={() => setDark(!dark)}>
Toggle Theme
</button>
);
};
// Component with dark mode
<div className="bg-white dark:bg-gray-800 text-gray-900 dark:text-white">
Content
</div>
カスタムユーティリティ
Tailwind の設定を拡張する
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
brand: {
50: '#f0f9ff',
100: '#e0f2fe',
// ... more shades
900: '#0c4a6e',
}
},
spacing: {
'128': '32rem',
},
animation: {
'fade-in': 'fadeIn 0.3s ease-in',
},
keyframes: {
fadeIn: {
'0%': { opacity: '0' },
'100%': { opacity: '1' },
}
}
}
}
};
コンポーネントライブラリのパターン
// components/ui/index.ts
export { Button } from './Button';
export { Card } from './Card';
export { Input } from './Input';
export { Badge } from './Badge';
// Usage
import { Button, Card } from '@/components/ui';
パフォーマンスのヒント
- JIT モードを使用する:使用されているクラスのみを生成します
- 未使用の CSS を削除する:コンテンツパスを正しく設定します
- コンポーネントを抽出する:クラスの重複を減らします
@applyは控えめに使用する:ユーティリティクラスを優先します- ユーティリティをグループ化する:エディタープラグインを使って整理します
ベストプラクティス
- モバイルファーストに従う:モバイルから始め、より大きなブレークポイントを追加します
- セマンティックなクラス名を使用する:抽出したコンポーネントに使用します
- 一貫性を保つ:設定ファイルのデザイントークンを使用します
- プラグインを活用する:Forms、Typography、aspect-ratio を使用します
- 関連するユーティリティをグループ化する:簡潔さより読みやすさを優先します
- 任意の値は控えめに使用する:
w-[137px]は最終手段とします - ダークモードを実装する:最初から計画に含めます
- レスポンシブ表示をテストする:すべてのブレークポイントを確認します
コメント
Markdown 対応