The skeleton component displays animated placeholder content while data is loading. It provides users with a visual indication that content is loading and gives them a sense of the structure and layout of the upcoming content. The component includes multiple variants, customizable sizing, and respects user motion preferences.
✅ Use skeletons when:
- Loading content that takes more than a few hundred milliseconds
- Displaying placeholder content during data fetching
- Maintaining layout structure during loading states
- Creating a smooth transition between loading and loaded states
- Providing visual feedback for better perceived performance
❌ Don't use skeletons for:
- Very fast loading content (under 200ms)
- Simple operations where a spinner is more appropriate
- One-time actions like form submissions
- Loading states that need specific progress information
The skeleton component supports three main variants to match different content types:
Control skeleton dimensions with the width and height properties to match your content layout:
The skeleton component supports different animation types to match your design needs:
The wave animation creates a sliding shimmer effect across the skeleton:
The pulse animation creates a breathing effect with opacity changes:
Create your own animations using the custom-keyframes attribute. This allows you to define custom CSS keyframes directly:
Compare different animation types side by side:
The skeleton component supports extensive customization through CSS custom properties and parts.
For simple customizations, use CSS custom properties directly on the component:
Experiment with custom skeleton styling using CSS parts and the custom-styles attribute. The skeleton component exposes the base CSS part for advanced styling. Try the presets below or create your own styles:
You can also use the custom-styles attribute to inject custom CSS directly into the component's shadow DOM:
- Use skeletons for content that takes longer than 200-300ms to load
- Prefer CSS animations over JavaScript for better performance
- Avoid too many animated skeletons on a single page
- Skeletons automatically include
role="status"andaria-label="Loading..." - The component respects
prefers-reduced-motionsettings - Ensure skeletons are replaced with actual content in a timely manner
- Provide alternative loading indicators for screen readers when needed
- Match skeleton shapes and sizes to the actual content layout
- Keep animation subtle and not distracting
- Use consistent skeleton patterns across your application
- Consider the user's context when choosing between animated and static skeletons
- Text skeletons should approximate actual text line heights
- Circular skeletons work well for avatars and profile pictures
- Rectangular skeletons are ideal for images, cards, and buttons
- Use width variations to create realistic text patterns
import { DapDSSkeleton } from 'dap-design-system'
import { DapDSSkeletonReact } from 'dap-design-system/react'
For optimal bundle sizes, use the tree-shakeable import syntax:
import { DapDSSkeleton } from 'dap-design-system/components'
| Property | Type | Default | Description |
|---|---|---|---|
variant | "text", "circular" , "rectangular" | 'text' | The variant of the skeleton. |
width | string, undefined | The width of the skeleton. Can be any valid CSS width value. | |
height | string, undefined | The height of the skeleton. Can be any valid CSS height value. | |
noAnimation | boolean | false | Whether to animate the skeleton. |
animation | "wave", "pulse" , "custom" | 'wave' | The animation type for the skeleton. |
customKeyframes | string, undefined | Custom keyframes for the animation when animation="custom". | |
| Should be a valid CSS keyframes string without the |
No slots available.
No custom events available.
| Part Name | Description |
|---|---|
base | The main skeleton container. |
You can style CSS parts using the ::part() pseudo-element selector:
/* Target a specific part */
.my-custom-dap-ds-skeleton::part(base) {
/* Your custom styles */
}
Example usage:
<dap-ds-skeleton class="my-custom-dap-ds-skeleton">
Skeleton
</dap-ds-skeleton>
.my-custom-dap-ds-skeleton::part(base) {
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
CSS parts allow you to style internal elements of the component while maintaining encapsulation. Learn more in our styling guide.
| Property Name | Description |
|---|---|
--dds-skeleton-base-color | Solid background color always visible (default: rgb(0 0 0 / 11%)); shown as a static block when prefers-reduced-motion is active |
--dds-skeleton-color | The shimmer overlay gradient (default: linear-gradient(90deg, transparent, rgb(0 0 0 / 10%), transparent)) |
--dds-skeleton-animation-duration | Duration of the loading animation (default: 1.5s) |
--dds-skeleton-border-radius | Border radius for rectangular skeletons (default: var(--dds-radius-small)) |
--dds-skeleton-text-spacing | Spacing between text lines in text variant (default: var(--dds-spacing-100)) |
--dds-skeleton-animation-timing-function | Timing function for the loading animation (default: ease-in-out) |
CSS custom properties (CSS variables) can be set directly on the component or in your stylesheet:
Method 1: Inline styles (Quick customization)
<dap-ds-skeleton
style="--dds-skeleton-base-color: value; --dds-skeleton-color: value;">
Skeleton
</dap-ds-skeleton>
Method 2: CSS classes (Reusable styles)
.my-custom-dap-ds-skeleton {
--dds-skeleton-base-color: value;
--dds-skeleton-color: value;
--dds-skeleton-animation-duration: value;
}
<dap-ds-skeleton class="my-custom-dap-ds-skeleton">
Skeleton
</dap-ds-skeleton>
Method 3: Global theme customization
/* Apply to all instances */
dap-ds-skeleton {
--dds-skeleton-base-color: value;
--dds-skeleton-color: value;
}
CSS custom properties inherit through the Shadow DOM, making them perfect for theming. Changes apply immediately without rebuilding.