<bmx-skeleton>
The grey shapes that hold a layout together while its content is on its way.
5 properties · 0 events · 0 methods · 2 parts
Example
label, and that is the rule: one announcement per region, on the outermost or
the first, and none on the rest. The whole graphic is aria-hidden, so a card with twelve of these in it
is silent instead of reading out twelve grey rectangles — but something has to say the content is coming, or a
page that is loading is indistinguishable from a page that is empty.
prefers-reduced-motion all three are the still one, and nothing is lost
by that — a skeleton says what it says through its shape, and a shape survives being motionless. That
is where it differs from an indeterminate <bmx-progress>, which cannot stop moving without
looking like a page that has hung.
Show markup
<div class="row" style="align-items: flex-start; gap: 1rem">
<bmx-skeleton shape="circle" label="Loading the profile"></bmx-skeleton>
<div style="flex: 1 1 20rem">
<bmx-skeleton lines="1" style="--bmx-skeleton-line-height: 1rem; --bmx-skeleton-gap: 0.75rem"></bmx-skeleton>
<div style="block-size: 0.75rem"></div>
<bmx-skeleton lines="3"></bmx-skeleton>
</div>
</div>
<div class="row" style="margin-block-start: 1.5rem">
<span class="note">
Only the avatar carries a <code>label</code>, and that is the rule: one announcement per region, on the outermost or
the first, and none on the rest. The whole graphic is <code>aria-hidden</code>, so a card with twelve of these in it
is silent instead of reading out twelve grey rectangles — but something has to say the content is coming, or a
page that is loading is indistinguishable from a page that is empty.
</span>
</div>
<div class="row" style="margin-block-start: 1rem; gap: 1.5rem; align-items: flex-start">
<div style="flex: 1 1 12rem">
<bmx-skeleton shape="block" style="--bmx-skeleton-size: 5rem"></bmx-skeleton>
<div style="block-size: 0.75rem"></div>
<bmx-skeleton lines="2"></bmx-skeleton>
</div>
<div style="flex: 1 1 12rem">
<bmx-skeleton shape="block" animation="pulse" style="--bmx-skeleton-size: 5rem"></bmx-skeleton>
<div style="block-size: 0.75rem"></div>
<bmx-skeleton lines="2" animation="pulse"></bmx-skeleton>
</div>
<div style="flex: 1 1 12rem">
<bmx-skeleton shape="block" animation="none" style="--bmx-skeleton-size: 5rem"></bmx-skeleton>
<div style="block-size: 0.75rem"></div>
<bmx-skeleton lines="2" animation="none"></bmx-skeleton>
</div>
</div>
<div class="row">
<span class="note">
Shimmer, pulse and still. Under <code>prefers-reduced-motion</code> all three are the still one, and nothing is lost
by that — a skeleton says what it says through its <em>shape</em>, and a shape survives being motionless. That
is where it differs from an indeterminate <code><bmx-progress></code>, which cannot stop moving without
looking like a page that has hung.
</span>
</div>
<bmx-skeleton shape="circle"></bmx-skeleton>
<bmx-skeleton lines="3" label="Loading your messages"></bmx-skeleton>
WHY THIS IS NOT bmx-progress
It looks like a member of the same family and it is a different thing entirely, in the one way that decides where a component boundary goes: what it is to somebody who cannot see it. A progress indicator reports a position - it has a role, a range and a value, and it is worth announcing. A skeleton reports nothing. It is a picture of a paragraph that has not arrived, and to a screen reader it should not exist at all.
That is the same judgement that made bmx-tooltip and bmx-popover two
components rather than one with a flag: a shape is a look and can be a
property, but a difference in what the accessibility tree is told is a
difference in what the element is. Folded into bmx-progress as a third
shape, this would be a progressbar with no value that must not be
announced - which is a contradiction that would have to be papered over on
every render.
SAY IT ONCE
The whole graphic is aria-hidden, so a card with twelve skeletons in it is
silent rather than reading out twelve grey rectangles. But something
should say the content is coming, or a screen-reader user meets a page that
is simply empty and has no way to tell whether it is loading or finished.
So label puts one polite announcement on this skeleton, and the rule is to
put it on one of them - the outermost, or the first - and leave it off
the rest. Announcing per skeleton is the failure this property exists to
make easy to avoid.
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
animation |
animation |
'shimmer' | 'pulse' | 'none' |
'shimmer' |
The idle animation. shimmer is a highlight travelling across the shape; pulse fades it in and out; none is a still grey box. Under prefers-reduced-motion all three are the still box - unlike an indeterminate progress bar, a skeleton that stops moving still says exactly what it said before, because the information is in the shape rather than in the motion. |
label |
label |
string |
— | A polite announcement that content is loading. Put it on one skeleton per region and leave it off the rest. See above. |
lastLine |
last-line |
number |
62 |
How wide the last line is, as a percentage. Shorter than the others by default, because the last line of a paragraph is - and a block of identical bars reads as a table rather than as text. |
lines |
lines |
number |
1 |
How many lines to draw, in text shape. |
shape |
shape |
BmxSkeletonShape |
'text' |
What it stands in for: lines of text, a block, or an avatar. |
CSS shadow parts
| Part | Description |
|---|---|
line |
Each bar in a text skeleton. |
shape |
The single box or circle, in the other two shapes. |
CSS custom properties
| Property | Description |
|---|---|
--bmx-skeleton-color |
The grey the shapes are drawn in. |
--bmx-skeleton-duration |
One cycle of the animation. |
--bmx-skeleton-gap |
The space between lines. |
--bmx-skeleton-highlight |
The band that travels across them in shimmer. |
--bmx-skeleton-line-height |
How thick one line of the text shape is. |
--bmx-skeleton-radius |
The corner radius of a line or a block. |
--bmx-skeleton-size |
The circle's diameter, and the block's height when no height is given. |