HySkeleton
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
html
<hy-skeleton></hy-skeleton>Circle skeleton (avatar placeholder)
html
<hy-skeleton shape="circle" width="48px" height="48px"></hy-skeleton>Text skeleton with multiple lines
html
<hy-skeleton shape="text" lines="3"></hy-skeleton>Different animation effects
html
<hy-skeleton effect="sheen"></hy-skeleton>
<hy-skeleton effect="pulse"></hy-skeleton>
<hy-skeleton effect="none"></hy-skeleton>Loading toggle with content
html
<hy-skeleton loading>
<p>This content shows when loading is false</p>
</hy-skeleton>Card skeleton with aria-busy on container
html
<!-- 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
html
<!-- 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>Slots
- default - Content to display when loading is false