Skip to content

Accessibility

A skeleton is a decorative loading placeholder — generic shapes that hold a page’s layout while its real content loads. Its accessible story is short: the shapes carry no information, so they stay hidden from assistive technology, while the loading state itself is announced once. Nothing inside a skeleton is interactive, so it never takes focus. Handled this way, it meets WCAG 2.1 AA.

  • Keep the placeholder fill distinguishable from the surface behind it on every supported theme, so the loading state reads for sighted users. Source: WCAG 1.4.3 Contrast (Minimum).
  • If the skeleton animates (pulse or shimmer), honour prefers-reduced-motion and fall back to a static fill — the motion plays automatically and continuously while content loads, so users who opt out of motion must be able to stop it. Source: WCAG 2.2.2 Pause, Stop, Hide.
  • Use semantic colour tokens rather than fixed values, so the placeholder adapts correctly across themes and surfaces.

A skeleton’s shapes are decorative stand-ins that carry no information, so hide them from assistive technology with aria-hidden="true" on the placeholder region — otherwise a screen reader announces a run of empty shapes. Announce the loading state once, on the container that will receive the content: set aria-busy="true" there (or expose a single polite live region), and remove it when the real content arrives — announce the state on the container, never once per shape. Nothing inside a skeleton is focusable and it holds no controls, so focus never lands on placeholder content and is never trapped; don’t add tabindex or real controls to a region that is only standing in for content.

<section aria-busy="true">
<div class="tng-stack align-items-stretch" aria-hidden="true">
<div class="tng-skeleton" style="--tng-skeleton-size: 140px;"></div>
<div class="tng-skeleton is-line"></div>
<div class="tng-skeleton is-line is-sm"></div>
</div>
</section>