Skeleton / Spinner
Description
Section titled “Description”Two loading primitives in one file:
.bp-skeleton— block placeholder with shimmer animation. Use it to represent content that is loading (text lines, headings, images, cards)..bp-spinner— inline rotating arc. Use it for actions in progress (form submit, button loading state).
Both respect prefers-reduced-motion — animation stops, shape remains visible.
Skeleton
Section titled “Skeleton”Text lines
<div style="display:flex;flex-direction:column;gap:0.5rem;max-width:24rem"><span class="bp-skeleton bp-skeleton--heading" style="width:40%"></span><span class="bp-skeleton bp-skeleton--text"></span><span class="bp-skeleton bp-skeleton--text"></span><span class="bp-skeleton bp-skeleton--text" style="width:70%"></span></div>Card skeleton
<div class="demo-skeleton-card"><span class="bp-skeleton bp-skeleton--rect demo-skeleton-card__image"></span><div class="demo-skeleton-card__body"> <span class="bp-skeleton bp-skeleton--heading" style="width:55%"></span> <span class="bp-skeleton bp-skeleton--text"></span> <span class="bp-skeleton bp-skeleton--text" style="width:80%"></span></div></div>Avatar + text
<div class="demo-skeleton-user"><span class="bp-skeleton bp-skeleton--circle demo-skeleton-user__avatar"></span><div class="demo-skeleton-user__lines"> <span class="bp-skeleton bp-skeleton--text demo-skeleton-user__name"></span> <span class="bp-skeleton bp-skeleton--text demo-skeleton-user__sub"></span></div></div>Spinner
Section titled “Spinner”Default
<span class="bp-spinner" role="status" aria-label="Loading"></span>Sizes
<span class="bp-spinner demo-spinner--sm" role="status" aria-label="Loading"></span><span class="bp-spinner" role="status" aria-label="Loading"></span><span class="bp-spinner demo-spinner--lg" role="status" aria-label="Loading"></span>Button loading state
<button class="bp-btn bp-btn--primary demo-btn-loading" disabled><span class="bp-spinner demo-btn-loading__spinner" role="status" aria-label="Saving"></span>Saving…</button>Public API
Section titled “Public API”Skeleton
Section titled “Skeleton”| Variable | Default | Description |
|---|---|---|
--skeleton-color | --bp-color-bg-subtle | Base color |
--skeleton-highlight | --bp-color-bg-elevated | Shimmer highlight color |
--skeleton-radius | --bp-radius-md | Border radius |
--skeleton-duration | 1.5s | Shimmer animation duration |
Spinner
Section titled “Spinner”| Variable | Default | Description |
|---|---|---|
--spinner-color | 20% primary, transparent | Track color (semi-transparent arc) |
--spinner-color-active | --bp-primary | Arc color |
--spinner-size | 1.5rem | Diameter |
--spinner-width | 2px | Stroke width |
--spinner-duration | 0.7s | Rotation duration |
Shape variants
Section titled “Shape variants”| Class | Shape |
|---|---|
.bp-skeleton--text | Full-width, 1em tall — for body text lines |
.bp-skeleton--heading | 60% wide, 1.5em tall — for headings |
.bp-skeleton--circle | border-radius: 50% — for avatars |
.bp-skeleton--rect | No border radius — for images |
All variants are display: block. Set width and height (or aspect-ratio) on the element or via a wrapper class.
✓ No axe violations tested 2026-05-11
WCAG criteria covered:
Accessibility
Section titled “Accessibility”- Add
role="status"andaria-label="Loading"to.bp-spinnerso screen readers announce the loading state. - Skeleton placeholders are purely visual — no role or label needed. Screen readers will skip them.
- Both components stop animating under
prefers-reduced-motion: reduce. The skeleton becomes a static block; the spinner keeps its shape but stops rotating.
Browser APIs
Section titled “Browser APIs”| API | Availability | Used for | Without it |
|---|---|---|---|
@keyframes | Widely available Baseline 2012 | Shimmer and spin animations | Static blocks/borders |
prefers-reduced-motion | Widely available Baseline 2020 | Disabling animation | Animation always plays |