Skip to content

HySkeleton

Usage examples on this page are written for Lit / plain HTML (<hy-skeleton>). The same component ships as HySkeleton in @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

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>

API

Properties

PropertyAttributeTypeDefaultDescription
shapeshape'rectangle' | 'circle' | 'text''rectangle'The shape of the skeleton placeholder.
effecteffect'sheen' | 'pulse' | 'none''sheen'The animation effect for the skeleton.
widthwidthstring | undefined'100%' (rectangle/text) or '48px' (circle)Width of the skeleton. Accepts any valid CSS value.
heightheightstring | undefined'1rem' (rectangle) or same as width (circle)Height of the skeleton. Accepts any valid CSS value.
radiusradiusstring | undefined'var(--hy-radius-container-sm)'Border radius for rectangle shape. Accepts any valid CSS value.
loadingloadingbooleantrueWhether the skeleton is in loading state.
lineslinesnumber1Number of text lines to render.

Slots

SlotDescription
defaultContent to display when loading is false

CSS Parts

PartDescription
baseThe skeleton element container
skeletonThe skeleton placeholder element
lineIndividual text line element (for shape="text")

CSS Custom Properties

PropertyDescription
--hy-skeleton-heightHeight of the rectangle skeleton
--hy-skeleton-circle-sizeSize of the circle skeleton
--hy-skeleton-text-line-heightHeight of each text line
--hy-skeleton-text-gapGap between text lines
--hy-skeleton-animation-durationDuration of skeleton animation
--hy-skeleton-animation-easingEasing of the skeleton loading animation

Built with Lit. Documented with VitePress.