How to Implement Skeleton Loading with Claude Code
Learn how to implement skeleton loading using Claude Code. Includes practical code examples and step-by-step guidance.
スケルトンローディングの効果
スケルトンローディング(スケルトンスクリーン)は、コンテンツ読み込み中にレイアウトの骨格を表示するUIパターンです。スピナーよりも体感速度が速く感じられ、レイアウトシフトも防げます。Claude Codeなら、再利用可能なスケルトンコンポーネントを素早く構築できます。
基本のスケルトンコンポーネント
> 汎用的なスケルトンコンポーネントを作って。
> テキスト、画像、カードの3パターンに対応して。
interface SkeletonProps {
width?: string | number;
height?: string | number;
variant?: 'text' | 'circular' | 'rectangular';
className?: string;
lines?: number;
}
function Skeleton({ width, height, variant = 'text', className = '', lines = 1 }: SkeletonProps) {
const baseClass = 'animate-pulse bg-gray-200 dark:bg-gray-700';
const variantClass = {
text: 'rounded',
circular: 'rounded-full',
rectangular: 'rounded-lg',
}[variant];
if (variant === 'text' && lines > 1) {
return (
<div className={`space-y-2 ${className}`}>
{Array.from({ length: lines }).map((_, i) => (
<div
key={i}
className={`${baseClass} rounded h-4`}
style={{ width: i === lines - 1 ? '75%' : '100%' }}
/>
))}
</div>
);
}
return (
<div
className={`${baseClass} ${variantClass} ${className}`}
style={{
width: width ?? (variant === 'text' ? '100%' : undefined),
height: height ?? (variant === 'text' ? '1rem' : undefined),
}}
role="status"
aria-label="読み込み中"
/>
);
}
カード型スケルトン
function CardSkeleton() {
return (
<div className="border rounded-lg p-4 space-y-4" aria-busy="true" aria-label="読み込み中">
<Skeleton variant="rectangular" height={200} />
<Skeleton variant="text" width="60%" height={24} />
<Skeleton variant="text" lines={3} />
<div className="flex items-center gap-3">
<Skeleton variant="circular" width={40} height={40} />
<div className="flex-1">
<Skeleton variant="text" width="40%" />
<Skeleton variant="text" width="25%" className="mt-1" />
</div>
</div>
</div>
);
}
function CardListSkeleton({ count = 3 }: { count?: number }) {
return (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{Array.from({ length: count }).map((_, i) => (
<CardSkeleton key={i} />
))}
</div>
);
}
コンテンツとスケルトンの切り替え
interface AsyncContentProps<T> {
data: T | undefined;
loading: boolean;
skeleton: React.ReactNode;
children: (data: T) => React.ReactNode;
error?: Error | null;
}
function AsyncContent<T>({ data, loading, skeleton, children, error }: AsyncContentProps<T>) {
if (error) {
return <div role="alert" className="text-red-500">エラーが発生しました</div>;
}
if (loading || !data) {
return <>{skeleton}</>;
}
return <>{children(data)}</>;
}
// Usage example
function UserProfile() {
const { data, loading, error } = useQuery('/api/user');
return (
<AsyncContent
data={data}
loading={loading}
error={error}
skeleton={<ProfileSkeleton />}
>
{(user) => (
<div>
<img src={user.avatar} alt={user.name} />
<h2>{user.name}</h2>
<p>{user.bio}</p>
</div>
)}
</AsyncContent>
);
}
CSSアニメーションの最適化
/* パルスアニメーション */
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.4; }
}
.animate-pulse {
animation: pulse 1.5s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
/* シマーエフェクト(よりリッチな表現) */
@keyframes shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
.animate-shimmer {
background: linear-gradient(
90deg,
#e5e7eb 25%,
#f3f4f6 50%,
#e5e7eb 75%
);
background-size: 200% 100%;
animation: shimmer 1.5s ease-in-out infinite;
}
Summary
Claude Codeを使えば、汎用スケルトンコンポーネントから用途別のパターン、シマーエフェクトまで効率的に構築できます。パフォーマンス全般についてはパフォーマンス最適化を、画像読み込みの最適化は画像遅延読み込みを参照してください。
スケルトンスクリーンのUXについてはNielsen Norman Group - Skeleton Screensが参考になります。
#Claude Code
#skeleton
#ローディング
#React
#UX
Related Posts
Tips & Tricks
Tips & Tricks
10 Tips to Triple Your Productivity with Claude Code
Learn about 10 tips to triple your productivity using Claude Code. Practical tips and code examples included.
Tips & Tricks
Tips & Tricks
Canvas/WebGL Optimization with Claude Code
Learn about canvas/webgl optimization using Claude Code. Practical tips and code examples included.
Tips & Tricks
Tips & Tricks
Markdown Implementation with Claude Code
Learn about markdown implementation using Claude Code. Practical tips and code examples included.