Skeleton
A decorative placeholder shown while content loads. Mark instances aria-hidden="true" and set aria-busy on the region they replace. Honors prefers-reduced-motion.
Loading card
Section titled “Loading card”<div
role="status"
aria-busy="true"
aria-label="Loading"
style="display: flex; gap: var(--re-space-3); align-items: center; width: min(22rem, 100%)"
>
<div
class="re-skeleton"
data-shape="circle"
aria-hidden="true"
style="width: 3rem; height: 3rem; flex: none"
></div>
<div style="flex: 1; display: grid; gap: var(--re-space-2)">
<div class="re-skeleton" data-shape="text" aria-hidden="true" style="width: 70%"></div>
<div class="re-skeleton" data-shape="text" aria-hidden="true" style="width: 40%"></div>
</div>
</div> <div class="re-skeleton" aria-hidden="true" style="max-width: 22rem; height: 8rem"></div> Accessibility
Section titled “Accessibility”- Semantics — Each
.re-skeletonis a non-interactive<div>with no role and is not focusable, so there is no keyboard interaction. The placeholders are purely decorative: mark themaria-hidden="true"so assistive technology skips them. - Loading state — Announce the load on the region the skeleton replaces, not on the placeholder. The card demo wraps the placeholders in
role="status"witharia-busy="true"andaria-label="Loading", so screen readers announce “Loading” while the content is pending; cleararia-busy(or swap in the real content) once it arrives. - Reduced motion — The shimmer is animated by default but fully disabled under
prefers-reduced-motion: reduce(both the animation and the moving gradient are removed), leaving a static muted block.
See the accessibility guide for shared patterns.