Skeleton

A skeleton holds the place of content that is still loading, as a gray shape sized like what will arrive. Choose text for a line of type and regular for a block, and the layout stays put when the content appears, with no reduced-motion code on your side. Below, a profile feed waits to load in every animation.

Reference docs⁠

BlazorReactWebOverviewExamplesAPIStylingAccessibility

Choosing a loading indicator⁠

Three kinds of indicator tell the reader to wait. Each suits a different job:

  • Linear progress indicator: how far a task has got, or that it is still running, on a bar across the content, such as a file upload.
  • Circular progress indicator: the same, in a compact ring, such as inside a button while it saves.
  • Skeleton: the shape of content that is still loading, such as gray lines where a list will appear.

Two jobs belong elsewhere. A count or status on an icon is a badge, and a message once the work is done is a toast.

Choosing a variant⁠

Two variants shape the placeholder to the content it replaces:

  • Text: a line one em high, for each line of a heading, a paragraph, or a caption.
  • Regular: a block that fills its parent, for an image, an avatar, or a card.

Built in⁠

  • animation runs a wave unless your style configuration says otherwise; pulse and none are the other two.
  • A reader who asks for reduced motion sees a still placeholder, with no code on your side.
  • aria-label names the placeholder "Loading content" until you say what is loading.
  • Assistive technology is told the area is loading, with no code on your side.

Using skeletons well⁠

  • Draw one text skeleton for each line of text and one regular skeleton at the size of each image or card.
  • Show the skeleton or the content, never both. Remove the skeleton when the content arrives.
  • Say what is loading in each skeleton's label, such as "Loading profile".
  • Put a regular skeleton in a parent that has a height.

Variants⁠

A variant of text draws a line one em high, so size it with font-size. A regular skeleton fills its parent, which needs a height. Omit variant and the skeleton takes it from your style configuration, which is regular unless you have changed it.

Children of a skeleton are never displayed.

Animation⁠

animation takes wave, pulse, or none. Omit it and the skeleton takes the animation from your style configuration, which is wave unless you have changed it.

In context⁠

Show skeletons shaped like the content while it loads, then remove them. Give each an aria-label that says what is loading, such as "Loading photo". Leave role (status) and aria-busy (true) at their defaults, and assistive technology is told the area is loading.

Properties⁠

PropertyAttributeTypeDescription
animationanimationnone, pulse, waveSkeletonAnimationSkeletonAnimation.None, .Pulse, .Wavedefault SkeletonAnimation.Wave, from the style configurationSets how the placeholder animates while loading. The animation stops for users who prefer reduced motion. See Animation.
ariaBusyaria-busystringdefault trueTells a screen reader the placeholder is still loading. Set "false" to mark it as not busy. See In context.
ariaLabelaria-labelstringdefault Loading contentThe name a screen reader announces for the placeholder. Set it to say what is loading. See In context.
rolerolestringdefault statusThe role assistive technology gives the placeholder. status makes it a polite live region. See In context.
variantvariantregular, textSkeletonVariantSkeletonVariant.Regular, .Textdefault SkeletonVariant.Regular, from the style configurationSets whether the placeholder is a line of text, 1em high, or a block that fills its container. See Variants.

The skeleton has no width or height member, so CSS on the skeleton or its parent sizes it.

Props⁠

PropTypeDescription
animationSkeletonAnimationTypeSkeletonAnimation.None, .Pulse, .Wavedefault SkeletonAnimation.Wave, from the style configurationSets how the placeholder animates while loading. The animation stops for users who prefer reduced motion. See Animation.
ariaBusystringdefault trueTells a screen reader the placeholder is still loading. Set "false" to mark it as not busy. See In context.
variantSkeletonVariantTypeSkeletonVariant.Regular, .Textdefault SkeletonVariant.Regular, from the style configurationSets whether the placeholder is a line of text, 1em high, or a block that fills its container. See Variants.

The skeleton has no width or height member, so CSS on the skeleton or its parent sizes it.

Parameters⁠

ParameterTypeDescription
AnimationSkeletonAnimation?SkeletonAnimation.None, .Pulse, .Wavedefault SkeletonAnimation.Wave, from the style configurationSets how the placeholder animates while loading. The animation stops for users who prefer reduced motion. See Animation.
AriaBusystring?default trueTells a screen reader the placeholder is still loading. Set "false" to mark it as not busy. See In context.
AriaLabelstring?default Loading contentThe name a screen reader announces for the placeholder. Set it to say what is loading. See In context.
Rolestring?default statusThe role assistive technology gives the placeholder. status makes it a polite live region. See In context.
VariantSkeletonVariant?SkeletonVariant.Regular, .Textdefault SkeletonVariant.Regular, from the style configurationSets whether the placeholder is a line of text, 1em high, or a block that fills its container. See Variants.

The skeleton has no width or height member, so CSS on the skeleton or its parent sizes it.

Inputs⁠

InputTypeDescription
animationSkeletonAnimationTypeSkeletonAnimation.None, .Pulse, .Wavedefault SkeletonAnimation.Wave, from the style configurationSets how the placeholder animates while loading. The animation stops for users who prefer reduced motion. See Animation.
ariaBusystringdefault trueTells a screen reader the placeholder is still loading. Set "false" to mark it as not busy. See In context.
ariaLabelstringdefault Loading contentThe name a screen reader announces for the placeholder. Set it to say what is loading. See In context.
rolestringdefault statusThe role assistive technology gives the placeholder. status makes it a polite live region. See In context.
variantSkeletonVariantTypeSkeletonVariant.Regular, .Textdefault SkeletonVariant.Regular, from the style configurationSets whether the placeholder is a line of text, 1em high, or a block that fills its container. See Variants.

The skeleton has no width or height member, so CSS on the skeleton or its parent sizes it.

Props⁠

PropTypeDescription
animationSkeletonAnimationTypeSkeletonAnimation.None, .Pulse, .Wavedefault SkeletonAnimation.Wave, from the style configurationSets how the placeholder animates while loading. The animation stops for users who prefer reduced motion. See Animation.
ariaBusystringdefault trueTells a screen reader the placeholder is still loading. Set "false" to mark it as not busy. See In context.
ariaLabelstringdefault Loading contentThe name a screen reader announces for the placeholder. Set it to say what is loading. See In context.
rolestringdefault statusThe role assistive technology gives the placeholder. status makes it a polite live region. See In context.
variantSkeletonVariantTypeSkeletonVariant.Regular, .Textdefault SkeletonVariant.Regular, from the style configurationSets whether the placeholder is a line of text, 1em high, or a block that fills its container. See Variants.

The skeleton has no width or height member, so CSS on the skeleton or its parent sizes it.

Props⁠

PropTypeDescription
animationSkeletonAnimationTypeSkeletonAnimation.None, .Pulse, .Wavedefault SkeletonAnimation.Wave, from the style configurationSets how the placeholder animates while loading. The animation stops for users who prefer reduced motion. See Animation.
ariaBusystringdefault trueTells a screen reader the placeholder is still loading. Set "false" to mark it as not busy. See In context.
ariaLabelstringdefault Loading contentThe name a screen reader announces for the placeholder. Set it to say what is loading. See In context.
rolestringdefault statusThe role assistive technology gives the placeholder. status makes it a polite live region. See In context.
variantSkeletonVariantTypeSkeletonVariant.Regular, .Textdefault SkeletonVariant.Regular, from the style configurationSets whether the placeholder is a line of text, 1em high, or a block that fills its container. See Variants.

The skeleton has no width or height member, so CSS on the skeleton or its parent sizes it.

Each attribute value has its own tokens; a cell shows its token's value, and selecting the cell shows the token's fallback path, with each name and value ready to copy. For example, the regular column's corner-radius row is --ct-skeleton-regular-corner-radius, which defaults to --ct-sys-corner-radius-small.

Variant⁠

Nameregulartext
corner-radius--ct-sys-corner-radius-small --ct-skeleton-regular-corner-radius--ct-sys-corner-radius-extra-small --ct-skeleton-text-corner-radius

Other tokens⁠

These stay the same whatever the variant.

TokenValue
--ct-skeleton-container-color--ct-sys-color-on-surface --ct-skeleton-container-color
--ct-skeleton-container-opacity0.16 --ct-skeleton-container-opacity
--ct-skeleton-corner-radius--ct-sys-corner-radius-small --ct-skeleton-corner-radius

Names and states⁠

A screen reader announces a skeleton with the ARIA status role, which ARIA defines as a polite live region. No WAI-ARIA Authoring Practices pattern covers a loading placeholder.

  • aria-label is the accessible name. It defaults to "Loading content"; set it per skeleton to say what is loading, such as "Loading profile".
  • role defaults to status.
  • aria-busy defaults to true and also accepts false.
  • Set the name, role, and busy state with aria-label, role, and aria-busy. Any other ARIA attribute on a skeleton has no effect.
  • Remove the skeleton when the content arrives. Tell assistive technology the content has loaded, for example by placing it in a live region.

Keyboard and focus⁠

Key Action
None A skeleton takes no keyboard input.
  • It is not interactive: it takes no focus, fires no events, and passes clicks through to what is behind it.

Pointer and touch⁠

  • A skeleton is not a pointer target, so WCAG 2.5.8 Target Size (Minimum) has no touch target to measure.

Display settings⁠

  • Reduced motion: under a reduced-motion preference, the skeleton draws as none.

Standards⁠

With its defaults, a skeleton meets zero WCAG 2.2 success criteria on its own, because it takes no focus. Two depend on how you use it:

  • 2.2.2 Pause, Stop, Hide (A): the animation starts on its own, so set animation to none for a wait that can run past five seconds.
  • 4.1.3 Status Messages (AA): tell assistive technology when the content has loaded, for example by placing it in a live region.