Skip to content
lab components / Feedback

Skeleton

Display placeholder shapes while content is loading to indicate something is on its way

This is a Lab component!

That means it doesn't satisfy our definition of done and may be changed or even deleted. For an exact status, please reach out to the Fancy team through the dev_fancy or ux_fancy channels.

import { Skeleton } from "@siteimprove/fancylab";

#Examples

Combine skeleton variants to match the layout of the content that is loading. Stack line variants for text, use block for images or card areas, and circle for avatars.

#Basic variants

Theme: agentic-ai-2025
<Content flexDirection="column" gap="small" style={{ width: 400 }}> <Skeleton variant="line-large" /> <Skeleton variant="line-medium" /> <Skeleton variant="line-small" /> <Skeleton variant="block" /> <Skeleton variant="circle" /> </Content>

#Text paragraph

Theme: agentic-ai-2025
<Content flexDirection="column" gap="small" style={{ width: 400 }}> <Skeleton variant="line-large" /> <Skeleton variant="line-large" /> <Skeleton variant="line-medium" width="75%" /> </Content>

#Card content

Theme: agentic-ai-2025
<Card aria-label="Loading card" style={{ width: 320 }}> <Card.Header> <Skeleton variant="line-large" width="60%" /> </Card.Header> <Content flexDirection="column" gap="small"> <Skeleton variant="block" /> <Skeleton variant="line-large" width="80%" /> <Skeleton variant="line-medium" width="55%" /> </Content> </Card>

#User profile

Theme: agentic-ai-2025
<Content gap="small" alignItems="center" style={{ width: 300 }}> <Skeleton variant="circle" /> <div style={{ flex: 1, display: "flex", flexDirection: "column", gap: "var(--space--xx-small)", }} > <Skeleton variant="line-large" width="60%" /> <Skeleton variant="line-small" width="40%" /> </div> </Content>

#Table rows

Loading table
TitleDescriptionTags
Theme: agentic-ai-2025
<BaseTable caption="Loading table" withoutKeyColumn rowKey={(item) => item.id} items={skeletonRows} columns={[ { header: "Title", render: () => <Skeleton variant="line-medium" />, }, { header: "Description", render: () => <Skeleton variant="line-medium" />, }, { header: "Tags", render: () => <Skeleton variant="line-medium" />, }, ]} />

#Form fields

Theme: agentic-ai-2025
<Content flexDirection="column" gap="medium"> <FormElementWrapper label="Username" name="username"> <Skeleton variant="line-large" height={36} /> </FormElementWrapper> <FormElementWrapper label="Email" name="email"> <Skeleton variant="line-large" height={36} /> </FormElementWrapper> </Content>

#Properties

Theme: agentic-ai-2025
PropertyDescriptionDefinedValue
variantRequired
"block" | "circle" | "line-large" | "line-medium" | "line-small"Shape of the loading placeholder
widthOptional
| string | numberOverride the default width
heightOptional
| string | numberOverride the default height
data-observe-keyOptional
stringUnique string, used by external script e.g. for event tracking
classNameOptional
stringCustom className that's applied to the outermost element (only intended for special cases)
styleOptional
objectStyle object to apply custom inline styles (only intended for special cases)

#Guidelines

#Best practices

  • Match the skeleton shape and dimensions to the content it represents.
  • Use line variants to represent text lines; use block for images, cards, or large content areas; use circle for avatars or icons.
  • Stack multiple skeletons to replicate the layout of the full content before it loads.
  • Remove all skeleton elements as soon as content is ready — do not keep skeletons visible alongside real content.

#Do not use when

  • The operation completes in under 300ms — prefer no loading indicator at all to avoid flashes.
  • The loading state is for a specific action in response to user input — use a Spinner instead.

#Accessibility

  • Skeleton elements are hidden from assistive technology via aria-hidden. Announce loading state to screen reader users by wrapping the area in a live region (role="status" or aria-live="polite") that updates when content is ready.
  • The shimmer animation is suppressed when the user has enabled "Reduce motion" in their OS settings.

#Writing

  • Skeleton components have no visible text — no writing guidelines apply.