HySkeleton
Usage examples on this page are written for Lit / plain HTML (
<hy-skeleton>). The same component ships asHySkeletonin@whitespaceux/harmony-react(native React 19), with typed wrappers for Angular, Solid, Svelte, and Vue. The API reference below applies to all frameworks.
A skeleton loading placeholder that indicates content is being loaded.
Skeleton components display a placeholder preview of content before the data loads, reducing perceived load time and preventing layout shift. They're ideal for content-heavy pages where loading spinners would be too intrusive.
Key Features:
- Three shape variants (rectangle, circle, text)
- Three animation effects (sheen, pulse, none)
- Customizable dimensions via props or CSS custom properties
- Loading toggle to show/hide skeleton vs content
- Multi-line text skeleton support
- SSR compatible
Accessibility Features:
- Uses
aria-hidden="true"on skeleton visuals (decorative) - Respects
prefers-reduced-motion(disables animations) - High contrast and forced colors mode support
- Not focusable (purely visual indicator)
Usage with aria-busy: Set aria-busy="true" on a parent container (not on the skeleton itself) to indicate loading state to assistive technologies. Remove or set to "false" when loading completes. Note: Screen reader support for aria-busy is limited (primarily JAWS 2020+).
When to Use:
- Page/section loading (< 10 seconds expected)
- Content placeholders for cards, lists, text
- Initial data fetch on page load
- Lazy-loaded content areas
When NOT to Use (prefer Spinner instead):
- Button loading states or form submissions
- Short operations or inline loading indicators
- Indeterminate progress with no content preview
- Very long operations (use Progress with percentage)
Examples
Basic rectangle skeleton
<hy-skeleton></hy-skeleton>Circle skeleton (avatar placeholder)
<hy-skeleton shape="circle" width="48px" height="48px"></hy-skeleton>Text skeleton with multiple lines
<hy-skeleton shape="text" lines="3"></hy-skeleton>Different animation effects
<hy-skeleton effect="sheen"></hy-skeleton>
<hy-skeleton effect="pulse"></hy-skeleton>
<hy-skeleton effect="none"></hy-skeleton>Loading toggle with content
<hy-skeleton loading>
<p>This content shows when loading is false</p>
</hy-skeleton>Card skeleton with aria-busy on container
<!-- Set aria-busy on the container, not the skeleton -->
<div class="card" aria-busy="true" aria-label="Loading card content">
<hy-skeleton shape="rectangle" height="200px"></hy-skeleton>
<hy-skeleton shape="circle" width="40px" height="40px"></hy-skeleton>
<hy-skeleton shape="text" lines="2"></hy-skeleton>
</div>Fill a sized container
<!-- The crop box has a definite height (aspect-ratio); height="100%"
stretches the skeleton to fill it with zero layout shift. -->
<div style="aspect-ratio: 1 / 1">
<hy-skeleton shape="rectangle" height="100%"></hy-skeleton>
</div>API
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
shape | shape | 'rectangle' | 'circle' | 'text' | 'rectangle' | The shape of the skeleton placeholder. |
effect | effect | 'sheen' | 'pulse' | 'none' | 'sheen' | The animation effect for the skeleton. |
width | width | string | undefined | '100%' (rectangle/text) or '48px' (circle) | Width of the skeleton. Accepts any valid CSS value. |
height | height | string | undefined | '1rem' (rectangle) or same as width (circle) | Height of the skeleton. Accepts any valid CSS value. |
radius | radius | string | undefined | 'var(--hy-radius-container-sm)' | Border radius for rectangle shape. Accepts any valid CSS value. |
loading | loading | boolean | true | Whether the skeleton is in loading state. |
lines | lines | number | 1 | Number of text lines to render. |
Slots
| Slot | Description |
|---|---|
default | Content to display when loading is false |
CSS Parts
| Part | Description |
|---|---|
base | The skeleton element container |
skeleton | The skeleton placeholder element |
line | Individual text line element (for shape="text") |
CSS Custom Properties
| Property | Description |
|---|---|
--hy-skeleton-height | Height of the rectangle skeleton |
--hy-skeleton-circle-size | Size of the circle skeleton |
--hy-skeleton-text-line-height | Height of each text line |
--hy-skeleton-text-gap | Gap between text lines |
--hy-skeleton-animation-duration | Duration of skeleton animation |
--hy-skeleton-animation-easing | Easing of the skeleton loading animation |