Skeleton
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
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
variant | variantreflects | SkeletonVariant | 'text' | |
shape | shapereflects | 'rectangle' | 'circle' | 'rectangle' | |
animated | animatedreflects | boolean | true | |
animation | animationreflects | 'wave' | 'pulse' | 'wave' | |
width | width | string | ||
height | height | string | ||
lines | lines | number | ||
testId | string | Test ID for automated testing From ZenoElement. |
Methods
| Method | Description |
|---|---|
focus(): void | Focus the component or its first focusable element From ZenoElement. |
blur(): void | Blur 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>withrole="presentation"andaria-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: reducethe wave and pulse animations are turned off. - With
prefers-contrast: morethe 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.
animatedis a Boolean that starts astrue, so only the property works:element.animated = false. - A paragraph with several lines is never animated. This layout also ignores
width,heightandanimation, and has nobasepart. - The placeholder has
aria-label="Loading"on an element that is alsoaria-hidden="true", so the label is never read. The text is fixed English. - A
paragraphwithoutlines, or withlines="1", renders one bar. The code has a default of three lines that is never reached.