# Skeleton Component Usage
## Overview
The skeleton component displays placeholder content while data is loading. Skeletons improve perceived performance by showing the structure of content before it loads, reducing layout shift and providing visual feedback to users.
## HTML Structure
### Basic Skeleton
```html
<div class="skeleton h-4 w-full"></div>
```
### Skeleton Variants
```html
<!-- Line skeleton -->
<div class="skeleton h-4 w-full rounded"></div>
<!-- Circle skeleton -->
<div class="skeleton size-10 rounded-full"></div>
<!-- Rectangle skeleton -->
<div class="skeleton h-32 w-full rounded-lg"></div>
```
## Common Patterns
### Text Line Skeleton
```html
<div class="space-y-2">
<div class="skeleton h-4 w-3/4 rounded"></div>
<div class="skeleton h-4 w-full rounded"></div>
<div class="skeleton h-4 w-5/6 rounded"></div>
</div>
```
### Avatar with Text
```html
<div class="flex items-center gap-4">
<div class="skeleton size-12 rounded-full"></div>
<div class="space-y-2 flex-1">
<div class="skeleton h-4 w-1/4 rounded"></div>
<div class="skeleton h-3 w-1/2 rounded"></div>
</div>
</div>
```
### Card Skeleton
```html
<div class="border rounded-lg p-4 space-y-4">
<div class="skeleton h-48 w-full rounded-lg"></div>
<div class="space-y-2">
<div class="skeleton h-4 w-3/4 rounded"></div>
<div class="skeleton h-3 w-1/2 rounded"></div>
</div>
<div class="skeleton h-10 w-full rounded-md"></div>
</div>
```
## Implementation Examples
### Profile Card Skeleton
```html
<div class="border rounded-lg p-6 space-y-4 max-w-sm">
<!-- Avatar and name -->
<div class="flex items-center gap-4">
<div class="skeleton size-16 rounded-full"></div>
<div class="space-y-2 flex-1">
<div class="skeleton h-5 w-32 rounded"></div>
<div class="skeleton h-4 w-24 rounded"></div>
</div>
</div>
<!-- Bio -->
<div class="space-y-2">
<div class="skeleton h-4 w-full rounded"></div>
<div class="skeleton h-4 w-5/6 rounded"></div>
<div class="skeleton h-4 w-4/6 rounded"></div>
</div>
<!-- Stats -->
<div class="flex gap-4">
<div class="space-y-1">
<div class="skeleton h-5 w-12 rounded"></div>
<div class="skeleton h-3 w-16 rounded"></div>
</div>
<div class="space-y-1">
<div class="skeleton h-5 w-12 rounded"></div>
<div class="skeleton h-3 w-16 rounded"></div>
</div>
<div class="space-y-1">
<div class="skeleton h-5 w-12 rounded"></div>
<div class="skeleton h-3 w-16 rounded"></div>
</div>
</div>
<!-- Button -->
<div class="skeleton h-10 w-full rounded-md"></div>
</div>
```
### Article List Skeleton
```html
<div class="space-y-6">
<!-- Article item 1 -->
<div class="flex gap-4">
<div class="skeleton size-20 rounded-lg shrink-0"></div>
<div class="space-y-2 flex-1">
<div class="skeleton h-5 w-3/4 rounded"></div>
<div class="skeleton h-4 w-full rounded"></div>
<div class="skeleton h-4 w-5/6 rounded"></div>
<div class="flex gap-4">
<div class="skeleton h-3 w-16 rounded"></div>
<div class="skeleton h-3 w-20 rounded"></div>
</div>
</div>
</div>
<!-- Article item 2 -->
<div class="flex gap-4">
<div class="skeleton size-20 rounded-lg shrink-0"></div>
<div class="space-y-2 flex-1">
<div class="skeleton h-5 w-2/3 rounded"></div>
<div class="skeleton h-4 w-full rounded"></div>
<div class="skeleton h-4 w-4/5 rounded"></div>
<div class="flex gap-4">
<div class="skeleton h-3 w-14 rounded"></div>
<div class="skeleton h-3 w-24 rounded"></div>
</div>
</div>
</div>
<!-- Article item 3 -->
<div class="flex gap-4">
<div class="skeleton size-20 rounded-lg shrink-0"></div>
<div class="space-y-2 flex-1">
<div class="skeleton h-5 w-4/5 rounded"></div>
<div class="skeleton h-4 w-full rounded"></div>
<div class="skeleton h-4 w-3/4 rounded"></div>
<div class="flex gap-4">
<div class="skeleton h-3 w-18 rounded"></div>
<div class="skeleton h-3 w-16 rounded"></div>
</div>
</div>
</div>
</div>
```
### Table Skeleton
```html
<div class="border rounded-lg overflow-hidden">
<!-- Header -->
<div class="flex gap-4 p-4 border-b bg-muted/50">
<div class="skeleton h-4 w-1/4 rounded"></div>
<div class="skeleton h-4 w-1/4 rounded"></div>
<div class="skeleton h-4 w-1/4 rounded"></div>
<div class="skeleton h-4 w-1/4 rounded"></div>
</div>
<!-- Rows -->
<div class="divide-y">
<div class="flex gap-4 p-4">
<div class="skeleton h-4 w-1/4 rounded"></div>
<div class="skeleton h-4 w-1/4 rounded"></div>
<div class="skeleton h-4 w-1/4 rounded"></div>
<div class="skeleton h-4 w-1/4 rounded"></div>
</div>
<div class="flex gap-4 p-4">
<div class="skeleton h-4 w-1/4 rounded"></div>
<div class="skeleton h-4 w-1/4 rounded"></div>
<div class="skeleton h-4 w-1/4 rounded"></div>
<div class="skeleton h-4 w-1/4 rounded"></div>
</div>
<div class="flex gap-4 p-4">
<div class="skeleton h-4 w-1/4 rounded"></div>
<div class="skeleton h-4 w-1/4 rounded"></div>
<div class="skeleton h-4 w-1/4 rounded"></div>
<div class="skeleton h-4 w-1/4 rounded"></div>
</div>
</div>
</div>
```
### Dashboard Stats Skeleton
```html
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
<!-- Stat card 1 -->
<div class="border rounded-lg p-4 space-y-2">
<div class="skeleton h-4 w-20 rounded"></div>
<div class="skeleton h-8 w-24 rounded"></div>
<div class="skeleton h-3 w-16 rounded"></div>
</div>
<!-- Stat card 2 -->
<div class="border rounded-lg p-4 space-y-2">
<div class="skeleton h-4 w-24 rounded"></div>
<div class="skeleton h-8 w-20 rounded"></div>
<div class="skeleton h-3 w-18 rounded"></div>
</div>
<!-- Stat card 3 -->
<div class="border rounded-lg p-4 space-y-2">
<div class="skeleton h-4 w-16 rounded"></div>
<div class="skeleton h-8 w-28 rounded"></div>
<div class="skeleton h-3 w-20 rounded"></div>
</div>
<!-- Stat card 4 -->
<div class="border rounded-lg p-4 space-y-2">
<div class="skeleton h-4 w-22 rounded"></div>
<div class="skeleton h-8 w-16 rounded"></div>
<div class="skeleton h-3 w-14 rounded"></div>
</div>
</div>
```
### Comment Skeleton
```html
<div class="space-y-4">
<div class="flex gap-3">
<div class="skeleton size-8 rounded-full shrink-0"></div>
<div class="space-y-2 flex-1">
<div class="flex items-center gap-2">
<div class="skeleton h-4 w-24 rounded"></div>
<div class="skeleton h-3 w-16 rounded"></div>
</div>
<div class="skeleton h-4 w-full rounded"></div>
<div class="skeleton h-4 w-3/4 rounded"></div>
</div>
</div>
<div class="flex gap-3">
<div class="skeleton size-8 rounded-full shrink-0"></div>
<div class="space-y-2 flex-1">
<div class="flex items-center gap-2">
<div class="skeleton h-4 w-20 rounded"></div>
<div class="skeleton h-3 w-12 rounded"></div>
</div>
<div class="skeleton h-4 w-5/6 rounded"></div>
</div>
</div>
</div>
```
### Form Skeleton
```html
<div class="space-y-6 max-w-md">
<!-- Form field 1 -->
<div class="space-y-2">
<div class="skeleton h-4 w-16 rounded"></div>
<div class="skeleton h-10 w-full rounded-md"></div>
</div>
<!-- Form field 2 -->
<div class="space-y-2">
<div class="skeleton h-4 w-20 rounded"></div>
<div class="skeleton h-10 w-full rounded-md"></div>
</div>
<!-- Form field 3 -->
<div class="space-y-2">
<div class="skeleton h-4 w-24 rounded"></div>
<div class="skeleton h-24 w-full rounded-md"></div>
</div>
<!-- Submit button -->
<div class="skeleton h-10 w-32 rounded-md"></div>
</div>
```
### Product Grid Skeleton
```html
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
<!-- Product 1 -->
<div class="space-y-3">
<div class="skeleton aspect-square w-full rounded-lg"></div>
<div class="skeleton h-4 w-3/4 rounded"></div>
<div class="skeleton h-4 w-1/2 rounded"></div>
<div class="skeleton h-5 w-1/4 rounded"></div>
</div>
<!-- Product 2 -->
<div class="space-y-3">
<div class="skeleton aspect-square w-full rounded-lg"></div>
<div class="skeleton h-4 w-2/3 rounded"></div>
<div class="skeleton h-4 w-1/2 rounded"></div>
<div class="skeleton h-5 w-1/3 rounded"></div>
</div>
<!-- Product 3 -->
<div class="space-y-3">
<div class="skeleton aspect-square w-full rounded-lg"></div>
<div class="skeleton h-4 w-4/5 rounded"></div>
<div class="skeleton h-4 w-3/5 rounded"></div>
<div class="skeleton h-5 w-1/4 rounded"></div>
</div>
<!-- Product 4 -->
<div class="space-y-3">
<div class="skeleton aspect-square w-full rounded-lg"></div>
<div class="skeleton h-4 w-3/4 rounded"></div>
<div class="skeleton h-4 w-2/5 rounded"></div>
<div class="skeleton h-5 w-1/3 rounded"></div>
</div>
</div>
```
## JavaScript Integration
### Show Skeleton While Loading
```javascript
async function loadContent() {
const container = document.getElementById('content');
const skeleton = document.getElementById('skeleton');
// Show skeleton
skeleton.classList.remove('hidden');
container.classList.add('hidden');
try {
const data = await fetchData();
// Hide skeleton, show content
skeleton.classList.add('hidden');
container.classList.remove('hidden');
// Render content
renderContent(container, data);
} catch (error) {
// Handle error
skeleton.classList.add('hidden');
showError(container, error);
}
}
```
### Conditional Skeleton
```javascript
function renderWithSkeleton(isLoading, container, skeletonHTML, contentHTML) {
if (isLoading) {
container.innerHTML = skeletonHTML;
} else {
container.innerHTML = contentHTML;
}
}
```
### React Pattern
```jsx
function UserCard({ user, isLoading }) {
if (isLoading) {
return (
<div className="flex items-center gap-4">
<div className="skeleton size-12 rounded-full" />
<div className="space-y-2">
<div className="skeleton h-4 w-32 rounded" />
<div className="skeleton h-3 w-24 rounded" />
</div>
</div>
);
}
return (
<div className="flex items-center gap-4">
<img src={user.avatar} className="size-12 rounded-full" />
<div>
<p className="font-medium">{user.name}</p>
<p className="text-sm text-muted-foreground">{user.email}</p>
</div>
</div>
);
}
```
## Accessibility Guidelines
### Screen Reader Considerations
```html
<div aria-busy="true" aria-label="Loading content">
<div class="skeleton h-4 w-full rounded" aria-hidden="true"></div>
<div class="skeleton h-4 w-3/4 rounded" aria-hidden="true"></div>
</div>
```
### Announcing Load State
```javascript
function setLoading(isLoading) {
const container = document.getElementById('content');
container.setAttribute('aria-busy', isLoading);
if (isLoading) {
// Announce to screen readers
const announcement = document.createElement('div');
announcement.setAttribute('role', 'status');
announcement.setAttribute('aria-live', 'polite');
announcement.className = 'sr-only';
announcement.textContent = 'Loading content...';
container.appendChild(announcement);
}
}
```
## Best Practices
### When to Use Skeletons
- Content loading from API
- Image/media loading
- Page transitions
- Data tables loading
- Any content with predictable structure
### When to Avoid Skeletons
- Very fast loads (< 200ms) - use nothing or subtle indicator
- Unknown content structure
- Error states
- Interactive elements that should be hidden
### Design Guidelines
- Match skeleton shape to final content
- Use realistic proportions
- Avoid too much animation (subtle pulse is best)
- Keep consistent spacing with final layout
- Don't overuse - 3-5 items is usually enough
### Performance Tips
- Keep skeleton HTML simple
- Avoid complex animations
- Use CSS animations instead of JavaScript
- Load skeleton styles inline if possible
- Transition smoothly to content