Skeleton
Loading placeholder with shimmer animation.
<arc-skeleton>Overview
Skeleton is a loading placeholder that mimics the shape of content before it arrives, reducing perceived wait times and preventing layout shift. It uses a shimmer animation (a linear gradient that sweeps left to right every 1.8 seconds) to signal that data is loading. It is less intrusive than a spinner and previews the page structure.
Three variant shapes cover common content patterns: text renders a single-line bar (full width, 1em height) for paragraph placeholders, circle produces a perfect circle for avatar placeholders (height auto-matches width when not explicitly set), and rect creates a rectangular block for images, cards, or media thumbnails. Custom width and height properties let you match the exact dimensions of the content being loaded.
The shimmer gradient uses --bg-elevated and --border-subtle tokens so the animation works in both light and dark themes. The component sets role="status", aria-label="Loading", and aria-busy="true" for screen reader users who cannot see the visual animation.
Guidelines
When to use
- Match skeleton dimensions to the actual content they replace to prevent layout shift
- Combine multiple skeletons to represent a full content layout (avatar + text lines)
- Use the text variant in a stack with varying widths for realistic paragraph placeholders
- Use the circle variant sized to match your avatar component dimensions
- Remove skeletons immediately when content loads: do not add artificial delays
When not to use
- Do not use skeletons for actions that take under 200ms: the flash is more distracting than helpful
- Do not stack more than 5-6 skeleton lines: it looks like a broken page rather than a loading state
- Do not use a rect skeleton without setting width and height: it will collapse to zero size
- Do not mix skeletons with spinners on the same screen; choose one loading pattern
- Do not animate skeleton opacity on top of the shimmer: the dual animation is visually noisy
Features
- Three shape variants: text (line), circle (avatar), and rect (block)
- Shimmer animation using a sweeping linear gradient at 1.8s intervals
- Custom width and height properties to match the content being loaded
- Circle variant auto-matches height to width when height is not set
- Theme-aware shimmer using `--bg-elevated` and `--border-subtle` tokens
- Accessibility attributes built in: `role="status"`, `aria-label`, and `aria-busy`
- CSS part (skeleton) for external animation or style overrides
Preview
Usage
<arc-skeleton variant="text" width="200px"></arc-skeleton>
<arc-skeleton variant="circle" width="48px"></arc-skeleton>
<arc-skeleton variant="rect" width="300px" height="120px"></arc-skeleton>import { Skeleton } from '@arclux/arc-ui-react';
export default function Example() {
return (
<>
<Skeleton variant="text" width="200px" />
<Skeleton variant="circle" width="48px" />
<Skeleton variant="rect" width="300px" height="120px" />
</>
);
}<script setup>
import { Skeleton } from '@arclux/arc-ui-vue';
</script>
<template>
<Skeleton variant="text" width="200px" />
<Skeleton variant="circle" width="48px" />
<Skeleton variant="rect" width="300px" height="120px" />
</template><script>
import { Skeleton } from '@arclux/arc-ui-svelte';
</script>
<Skeleton variant="text" width="200px" />
<Skeleton variant="circle" width="48px" />
<Skeleton variant="rect" width="300px" height="120px" />import { Component } from '@angular/core';
import { Skeleton } from '@arclux/arc-ui-angular';
@Component({
imports: [Skeleton],
template: `
<arc-skeleton variant="text" width="200px"></arc-skeleton>
<arc-skeleton variant="circle" width="48px"></arc-skeleton>
<arc-skeleton variant="rect" width="300px" height="120px"></arc-skeleton>
`,
})
export class MyComponent {}import { Skeleton } from '@arclux/arc-ui-solid';
export default function Example() {
return (
<>
<Skeleton variant="text" width="200px" />
<Skeleton variant="circle" width="48px" />
<Skeleton variant="rect" width="300px" height="120px" />
</>
);
}import { Skeleton } from '@arclux/arc-ui-preact';
export default function Example() {
return (
<>
<Skeleton variant="text" width="200px" />
<Skeleton variant="circle" width="48px" />
<Skeleton variant="rect" width="300px" height="120px" />
</>
);
}<!-- Auto-generated by @arclux/prism — do not edit manually -->
<!-- arc-skeleton — requires skeleton.css + base.css (or arc-ui.css) -->
<div class="arc-skeleton">
<div
class="skeleton"
role="status"
aria-label="Loading"
aria-busy="true"
></div>
</div><!-- Auto-generated by @arclux/prism — do not edit manually -->
<!-- arc-skeleton — self-contained, no external CSS needed -->
<div class="arc-skeleton" style="display: block">
<div
style="background: linear-gradient(
90deg,
rgb(17, 17, 22) 25%,
rgb(24, 24, 30) 37%,
rgb(17, 17, 22) 63%
); background-size: 200% 100%; animation: shimmer 1.8s ease-in-out infinite"
role="status"
aria-label="Loading"
aria-busy="true"
></div>
</div>API
widthstring''- CSS width value (e.g. "200px", "100%")
heightstring''- CSS height value; circle auto-matches width when omitted
variant'text' | 'circle' | 'rect''text'- Shape of the skeleton: text for lines, circle for avatars, rect for blocks
countnumber1- Renders multiple skeleton items stacked vertically with spacing. Useful for placeholder lists.