Skip to main content

Skeleton

Skeleton

Placeholder loading component that mimics content shape

Tags: component feedback loading

View Demo

Skeleton components show a placeholder preview of content before it loads, reducing perceived loading time.

Import​

<script>
  import { Skeleton } from '@classic-homes/theme-svelte';
</script>

Basic Usage​

<Skeleton class="h-4 w-full" />

Props​

Prop Type Default Description
variant 'default' | 'text' | 'avatar' | 'card' | 'button' | 'title' 'default' Predefined shape variant
animation 'pulse' | 'shimmer' | 'none' 'pulse' Animation style
class string - Additional CSS classes

Variants​

Default​

Custom sizing with classes:

<Skeleton class="h-4 w-full" />
<Skeleton class="h-8 w-64" />

Text​

Single line of text:

<Skeleton variant="text" /> <!-- h-4 w-full -->

Title​

Larger heading text:

<Skeleton variant="title" /> <!-- h-6 w-3/4 -->

Avatar​

Circular avatar placeholder:

<Skeleton variant="avatar" /> <!-- h-12 w-12 rounded-full -->

Card​

Card-sized placeholder:

<Skeleton variant="card" /> <!-- h-32 w-full -->

Button​

Button-sized placeholder:

<Skeleton variant="button" /> <!-- h-10 w-24 -->

Custom Sizing​

Use Tailwind classes for custom dimensions:

<!-- Custom width -->
<Skeleton class="h-4 w-32" />
<Skeleton class="h-4 w-1/2" />

<!-- Custom height -->
<Skeleton class="h-20 w-full" />

<!-- Custom shape -->
<Skeleton class="h-16 w-16 rounded-lg" />

Examples​

Text Content Loading​

<div class="space-y-2">
  <Skeleton variant="title" />
  <Skeleton variant="text" />
  <Skeleton variant="text" />
  <Skeleton class="h-4 w-2/3" />
</div>

User Card Loading​

<div class="flex items-center gap-4">
  <Skeleton variant="avatar" />
  <div class="space-y-2 flex-1">
    <Skeleton class="h-4 w-32" />
    <Skeleton class="h-3 w-24" />
  </div>
</div>

Card Loading​

<Card>
  <CardHeader>
    <Skeleton variant="title" />
    <Skeleton variant="text" class="mt-2" />
  </CardHeader>
  <CardContent>
    <Skeleton variant="card" />
  </CardContent>
  <CardFooter>
    <Skeleton variant="button" />
  </CardFooter>
</Card>

Table Row Loading​

<tr>
  <td><Skeleton class="h-4 w-8" /></td>
  <td><Skeleton class="h-4 w-32" /></td>
  <td><Skeleton class="h-4 w-48" /></td>
  <td><Skeleton class="h-4 w-24" /></td>
</tr>

Grid Loading​

<div class="grid grid-cols-3 gap-4">
  {#each Array(6) as _}
    <div class="space-y-2">
      <Skeleton class="h-32 w-full" />
      <Skeleton variant="title" />
      <Skeleton variant="text" />
    </div>
  {/each}
</div>

Profile Page Loading​

<div class="space-y-6">
  <!-- Header -->
  <div class="flex items-center gap-6">
    <Skeleton class="h-24 w-24 rounded-full" />
    <div class="space-y-2">
      <Skeleton class="h-8 w-48" />
      <Skeleton class="h-4 w-32" />
    </div>
  </div>

  <!-- Stats -->
  <div class="grid grid-cols-3 gap-4">
    {#each Array(3) as _}
      <Skeleton class="h-20" />
    {/each}
  </div>

  <!-- Content -->
  <div class="space-y-2">
    <Skeleton variant="text" />
    <Skeleton variant="text" />
    <Skeleton class="h-4 w-3/4" />
  </div>
</div>

Conditional Loading​

{#if loading}
  <div class="space-y-2">
    <Skeleton variant="title" />
    <Skeleton variant="text" />
    <Skeleton variant="text" />
  </div>
{:else}
  <div>
    <h2>{title}</h2>
    <p>{content}</p>
  </div>
{/if}

Image Loading​

<div class="relative">
  {#if imageLoading}
    <Skeleton class="h-64 w-full" />
  {/if}
  <img
    src={imageUrl}
    onload={() => (imageLoading = false)}
    class={imageLoading ? 'invisible absolute' : ''}
  />
</div>

Animation​

Control the animation style with the animation prop:

Pulse (default)​

Fades opacity in and out. Subtle and widely used:

<Skeleton animation="pulse" class="h-4 w-full" />

Shimmer​

A sweeping gradient highlight that moves across the element. More visually distinctive:

<Skeleton animation="shimmer" class="h-4 w-full" />

Great for card or media loading states where you want a polished feel:

<div class="border rounded-lg p-4 space-y-3">
  <Skeleton animation="shimmer" class="h-32 w-full rounded" />
  <Skeleton animation="shimmer" class="h-5 w-3/4" />
  <Skeleton animation="shimmer" class="h-4 w-full" />
</div>

None​

Static placeholder with no animation:

<Skeleton animation="none" class="h-4 w-full" />

Useful for print stylesheets or reduced-motion contexts where you want full control.

All animations are CSS-based, performant, and respect prefers-reduced-motion.

Accessibility​

  • Skeletons are decorative and don't need ARIA labels
  • Use aria-busy="true" on the container for screen readers
  • Provide loading state context when needed
<div aria-busy={loading} aria-live="polite">
  {#if loading}
    <Skeleton variant="text" />
  {:else}
    <p>{content}</p>
  {/if}
</div>
On this page