Skeleton
Skeleton loading patterns to display placeholder content while data is being fetched. Reduce perceived load time with animated placeholders.
Overview
Skeleton loaders create a visual preview of content that will appear, giving users an immediate sense of the page structure. They are preferable to spinners for content-heavy pages as they maintain layout stability and feel faster.
Key features:
- Pure CSS animation using
@keyframesfor smooth pulse effect - Accessible loading states with
aria-busy="true" - Flexible placeholder sizes matching your content dimensions
- Uses Vanilla Breeze CSS custom properties for consistent theming
- Layout primitives like
data-layout="stack"for structure
Text Placeholder
Display placeholder lines for text content like paragraphs. Use varying widths to simulate natural text flow, with the last line typically shorter.
Card Placeholder
A complete card skeleton with image placeholder, heading, text lines, and button. Use this pattern for product cards, blog posts, or any content card that loads asynchronously.
Table Placeholder
Table skeleton with real headers and placeholder rows. Includes avatar, checkbox, and various cell widths to match typical table layouts. Use this when loading tabular data.
CSS Animation
The skeleton animation uses a simple pulse effect that fades between two opacity values. This is performant and works across all browsers.
Configuration
Skeleton elements are built from CSS classes applied to placeholder elements. Here are the key styling options:
| Class | Purpose | Customization |
|---|---|---|
.skeleton |
Base class with animation | Change animation-duration for speed |
.skeleton-heading |
Heading placeholder | Adjust height and width |
.skeleton-line |
Text line placeholder | Set width per line for variety |
.skeleton-image |
Image placeholder | Adjust aspect-ratio to match images |
.skeleton-avatar |
Circular avatar placeholder | Set width/height for size |
.skeleton-button |
Button placeholder | Match your button dimensions |
Accessibility
- Add
aria-busy="true"to loading containers. Remove the attribute when content finishes loading. - Include an
aria-labeldescribing the loading state so screen readers announce meaningful context (e.g. "Loading card"). - Use
role="status"with a live region announcement when content finishes loading so assistive technology is notified. - Respect
prefers-reduced-motionby disabling or reducing animations for users who prefer it.
Animation Variants
You can customize the animation effect to match your brand or preferences:
Usage Notes
- Animation performance: The pulse animation only animates
opacity, which is highly performant. Avoid animating layout properties. - Layout stability: Match skeleton dimensions to actual content to prevent layout shift (CLS) when content loads.
- Duration: Use skeletons for loads under 3-5 seconds. For longer waits, consider progress indicators with estimated time.
Related
Feedback States
Unified empty, loading, and error states
Empty States
When there's no content to display
Error Pages
404, 500, and maintenance pages