Skip to main content

Skeleton

<zeno-skeleton>FeedbackSource

A grey placeholder in the shape of content that is still loading.

import '@usezeno/tokens/css';
import '@usezeno/core/web-components';

Examples​

Variants​

Each variant has a default width and height that matches the content it stands for.

<zeno-skeleton variant="title"></zeno-skeleton>
<zeno-skeleton variant="text"></zeno-skeleton>
<zeno-skeleton variant="avatar"></zeno-skeleton>
<zeno-skeleton variant="button"></zeno-skeleton>
<zeno-skeleton variant="input"></zeno-skeleton>
<zeno-skeleton variant="image"></zeno-skeleton>
<zeno-skeleton variant="card"></zeno-skeleton>

Paragraph with several lines​

With variant="paragraph" and lines above 1, the element renders one bar for each line. The last bar is shorter.

<zeno-skeleton variant="paragraph" lines="4"></zeno-skeleton>

Custom size and shape​

width and height take any CSS length. shape="circle" makes the placeholder round.

<zeno-skeleton width="12rem" height="1.5rem"></zeno-skeleton>
<zeno-skeleton shape="circle" width="4rem" height="4rem"></zeno-skeleton>

Animation​

The default animation is wave. The second placeholder uses pulse. The third has no animation: the script sets the animated property to false.

<zeno-skeleton variant="text"></zeno-skeleton>
<zeno-skeleton variant="text" animation="pulse"></zeno-skeleton>
<zeno-skeleton variant="text"></zeno-skeleton>
document.querySelectorAll('zeno-skeleton')[2].animated = false;

Placeholder for a list row​

<div style="display: flex; gap: 1rem; align-items: center">
<zeno-skeleton variant="avatar"></zeno-skeleton>
<div style="flex: 1; display: grid; gap: 0.5rem">
<zeno-skeleton variant="title"></zeno-skeleton>
<zeno-skeleton variant="text"></zeno-skeleton>
</div>
</div>

Attributes and properties​

PropertyAttributeTypeDefaultDescription
variantvariantreflectsSkeletonVariant'text'
shapeshapereflects'rectangle' | 'circle''rectangle'
animatedanimatedreflectsbooleantrue
animationanimationreflects'wave' | 'pulse''wave'
widthwidthstring
heightheightstring
lineslinesnumber
testIdstringTest ID for automated testing From ZenoElement.

Methods​

MethodDescription
focus(): voidFocus the component or its first focusable element From ZenoElement.
blur(): voidBlur the component or its focused element From ZenoElement.

Events​

This element sends no events.

Slots​

This element has no slots.

CSS parts​

Part
base
line

CSS custom properties​

This element documents no custom properties of its own. Style it through its parts and through the tokens it reads.

The element's own source reads no tokens.

Types​

type SkeletonVariant =
| 'text'
| 'title'
| 'paragraph'
| 'avatar'
| 'button'
| 'input'
| 'image'
| 'card';

Accessibility​

Keyboard​

This element handles no keys of its own.

Forms​

This element is not a form control. It adds nothing to a form's data.

Notes​

  • The placeholder is a <div> with role="presentation" and aria-hidden="true". Assistive technology does not see it, so the element does not announce that content is loading.
  • The element cannot take focus and has no keyboard behaviour.
  • With prefers-reduced-motion: reduce the wave and pulse animations are turned off.
  • With prefers-contrast: more the placeholder gets a border in system colours.

Tests and known gaps​

  • No tests of its own. The only check is that the element registers and renders (smoke.test.ts).
  • Not checked with axe-core.
  • Has no Storybook story.
9 of the 12 properties, methods, events, slots and parts above have no description in the source
  • the property variant
  • the property shape
  • the property animated
  • the property animation
  • the property width
  • the property height
  • the property lines
  • the part base
  • the part line

Known gaps:

  • The animation cannot be turned off from HTML. animated is a Boolean that starts as true, so only the property works: element.animated = false.
  • A paragraph with several lines is never animated. This layout also ignores width, height and animation, and has no base part.
  • The placeholder has aria-label="Loading" on an element that is also aria-hidden="true", so the label is never read. The text is fixed English.
  • A paragraph without lines, or with lines="1", renders one bar. The code has a default of three lines that is never reached.