Skeleton
Loading placeholders that mimic the shape of content before it arrives. Skeletons use a shimmering animation by default and support text lines, headings, circles (avatars), rectangles (images), buttons, inputs, lists, and grids — all composable to match your actual layout.
Text & Heading
Sizes
<!-- Heading placeholder -->
<div class="vd-skeleton vd-skeleton-heading"></div>
<!-- Text lines (last one auto-shorts to 80%) -->
<div class="vd-skeleton vd-skeleton-text"></div>
<div class="vd-skeleton vd-skeleton-text"></div>
<div class="vd-skeleton vd-skeleton-text"></div>
<!-- Text sizes -->
<div class="vd-skeleton vd-skeleton-text vd-skeleton-text-xs"></div>
<div class="vd-skeleton vd-skeleton-text vd-skeleton-text-sm"></div>
<div class="vd-skeleton vd-skeleton-text vd-skeleton-text-lg"></div>
<div class="vd-skeleton vd-skeleton-text vd-skeleton-text-xl"></div>Circles, Rectangles & Form Elements
Circles (avatars)
Rectangles (images)
Form elements
<!-- Circles (avatars) -->
<div class="vd-skeleton vd-skeleton-circle vd-skeleton-circle-xs"></div>
<div class="vd-skeleton vd-skeleton-circle vd-skeleton-circle-sm"></div>
<div class="vd-skeleton vd-skeleton-circle vd-skeleton-circle-md"></div>
<div class="vd-skeleton vd-skeleton-circle"></div>
<div class="vd-skeleton vd-skeleton-circle vd-skeleton-circle-lg"></div>
<div class="vd-skeleton vd-skeleton-circle vd-skeleton-circle-xl"></div>
<!-- Rectangles (images) -->
<div class="vd-skeleton vd-skeleton-rect" style="width:200px;"></div>
<div class="vd-skeleton vd-skeleton-rect vd-skeleton-rect-lg" style="width:200px;"></div>
<!-- Form placeholders -->
<div class="vd-skeleton vd-skeleton-input"></div>
<div class="vd-skeleton vd-skeleton-button"></div>
<div class="vd-skeleton vd-skeleton-button vd-skeleton-button-sm"></div>Composite: Card & List
Card placeholder
List placeholder
<!-- Card placeholder -->
<div class="vd-skeleton vd-skeleton-card">
<div class="vd-skeleton vd-skeleton-heading vd-mb-3"></div>
<div class="vd-skeleton vd-skeleton-text"></div>
<div class="vd-skeleton vd-skeleton-text"></div>
</div>
<!-- List placeholder -->
<div class="vd-skeleton vd-skeleton-list">
<div class="vd-skeleton-list-item">
<div class="vd-skeleton vd-skeleton-circle vd-skeleton-circle-sm"></div>
<div class="vd-skeleton-list-item-content">
<div class="vd-skeleton vd-skeleton-text vd-skeleton-text-sm"></div>
<div class="vd-skeleton vd-skeleton-text" style="width:70%;"></div>
</div>
</div>
</div>Grid & Width Utilities
Grid layout
Width utilities
No animation (static)
Pulse animation
<!-- Grid placeholder -->
<div class="vd-skeleton vd-skeleton-grid">
<div class="vd-skeleton vd-skeleton-rect"></div>
<div class="vd-skeleton vd-skeleton-rect"></div>
<div class="vd-skeleton vd-skeleton-rect"></div>
</div>
<!-- Width utilities -->
<div class="vd-skeleton vd-skeleton-text vd-skeleton-w-full"></div>
<div class="vd-skeleton vd-skeleton-text vd-skeleton-w-3-4"></div>
<div class="vd-skeleton vd-skeleton-text vd-skeleton-w-1-2"></div>
<div class="vd-skeleton vd-skeleton-text vd-skeleton-w-1-4"></div>
<!-- Static (no shimmer) -->
<div class="vd-skeleton vd-skeleton-static vd-skeleton-text"></div>
<!-- Pulse animation -->
<div class="vd-skeleton vd-skeleton-pulse vd-skeleton-text"></div>CSS Variables
| Variable | Default | Description |
|---|---|---|
--vd-skeleton-bg | var(--vd-color-gray-200) | Base placeholder color |
--vd-skeleton-shimmer | var(--vd-color-gray-100) | Shimmer highlight color |
--vd-skeleton-border-radius | var(--vd-btn-border-radius) | Default corner rounding |
API Reference
Usage
<script setup lang="ts">
import { VdSkeleton } from "@vanduo-oss/vd3";
</script>
<template>
<VdSkeleton shape="text" :lines="3" />
<VdSkeleton shape="circle" size="lg" />
<VdSkeleton shape="rect" width="200px" />
</template>CSS Classes
| Class | Description |
|---|---|
.vd-skeleton | Base placeholder with shimmer animation and overflow hidden. |
.vd-skeleton-text | Single text line (1rem height, 100% width, last sibling auto-shorts to 80%). |
.vd-skeleton-text-xs | Extra small text line (0.75rem). |
.vd-skeleton-text-sm | Small text line (0.875rem). |
.vd-skeleton-text-lg | Large text line (1.25rem). |
.vd-skeleton-text-xl | Extra large text line (1.5rem). |
.vd-skeleton-paragraph | Column wrapper for multiple text lines with built-in gap and progressive line widths. |
.vd-skeleton-heading | Heading placeholder (1.5rem, 60% width). |
.vd-skeleton-heading-lg | Large heading (2rem, 50% width). |
.vd-skeleton-circle | Circle shape (border-radius: 50%, 3rem default). |
.vd-skeleton-circle-xs … -xl | Circle sizes from 1.5rem to 5rem. |
.vd-skeleton-rect | Rectangle placeholder (100% width, 200px height). |
.vd-skeleton-rect-sm | Small rectangle (100px height). |
.vd-skeleton-rect-lg | Large rectangle (300px height). |
.vd-skeleton-button | Button placeholder (2.5rem height, 6rem width). |
.vd-skeleton-button-sm | Small button (2rem height, 4rem width). |
.vd-skeleton-button-lg | Large button (3rem height, 8rem width). |
.vd-skeleton-input | Input placeholder (2.5rem height, 100% width). |
.vd-skeleton-card | Card wrapper with padding and border. |
.vd-skeleton-list | Vertical flex list for rows with avatar + text. |
.vd-skeleton-list-item | Flex row with circle and content columns. |
.vd-skeleton-list-item-content | Content column inside a list item. |
.vd-skeleton-grid | CSS grid container for card/image placeholders. |
.vd-skeleton-table-row | Flex row placeholder for table-like loading states, with bottom border spacing. |
.vd-skeleton-w-* | Width utilities: -w-full, -w-3-4, -w-2-3, -w-1-2, -w-1-3, -w-1-4. |
.vd-skeleton-static | Disables the shimmer animation. |
.vd-skeleton-pulse | Replaces shimmer with an opacity pulse animation. |
Component API (Vue 3)
| Prop | Description |
|---|---|
:shape | text | circle | rect | card | button (default text). |
:size | sm | md | lg | xl (default md). |
:width | Explicit CSS width, e.g. "200px". |
:lines | Number of lines when shape="text" (default 1). |
Accessibility
- Always wrap skeleton placeholders in an
aria-live="polite"region and replace them with real content once loaded, so screen readers announce the change. - Use
aria-busy="true"on the container while skeletons are visible to indicate the region is updating. - Shimmer animation is disabled when
prefers-reduced-motion: reduceis active — the placeholder becomes a static color block. - Avoid leaving skeletons visible for extended periods. If loading takes more than a few seconds, show a progress indicator or retry option.
- Ensure skeleton colors maintain sufficient contrast against the page background in both light and dark themes.