Skip to content

Skeleton

Skeletons only where your component waits on data, drawn from its own markup. Everything else is already there.

01

Everything else is already there.

Only data

A skeleton goes on what comes from the data: a title, a price, a name, a photo. Labels, dividers, buttons and icons that are part of the design show as they are from the first frame. A skeleton says data goes here; on a button or a label it says something that isn't true, and hides what's already known.

The skill decides from your component's source and marks each element that shows data withdata-skeleton. In mixed text, only the data part is marked.

<Skeleton loading={isPlaceholderData}>
  <p>Order <span data-skeleton>{order.id}</span></p>
  <p>Total <span data-skeleton>{order.total}</span></p>
  <Button>Track order</Button>
</Skeleton>

Loading

Order #0000

Total$00.00

ArrivesDay, Mon 00

Loaded

Order #4821

Total$184.00

ArrivesThursday, Oct 23

Plate IThe labels and the button are the design. Only the order's values wait.
02

A bar per line, no border.

Text

Text from the data (titles, names, prices, dates, counts) becomes one filled bar per line, as long as that line, with square corners and no border. Text is most of what loads: quiet bars read as lines of text at any size, and keep the real text's line count and rhythm.

Loading

A short title

A description of a usual length, a sentence or two, long enough to run over two lines.

Loaded

Notes on a 1542 herbal

Five hundred woodcuts, each colored by hand. The plates were cut first, the text set around them, so every page is laid out like a garden.

Plate IIEach line is its own bar, ending where the line does.
03

Striped, with a border.

Pictures

Images and video become plates: a 1px border and diagonal stripes, the way a layout sketch marks where a picture goes. A round picture, like an avatar, stays round. A picture must never be mistaken for text, and stripes say picture at a glance.

Loading

Loaded

An album coverA video's first frameMira Demir
Plate IIIA cover, a video and an avatar: three pictures, three plates.
04

A drawing of the chart that's coming.

Charts

A chart becomes a drawing of itself: its axes and gridlines, as many bars or points as it will have, a bar where each label goes. A plate would only say picture; a chart's shape is known before its numbers are, and the drawing says which chart is coming and where it will sit. It fills the chart's box, its lines kept 1px, so nothing is measured.

Common charts have presets in a package. Any other chart, a sankey, a Gantt timeline, a box plot, the skill draws in one go from its name, its code or a screenshot, with the kit the presets are drawn with. While loading, the drawing stands in the chart's place:

import { BarChartSkeleton } from '@frontendsupply/chart-skeletons';

<Skeleton loading={isPending} className="h-45 w-full">
  {isPending ? (
    <BarChartSkeleton width={320} height={180} bars={7} />
  ) : (
    <OrdersChart data={data} />
  )}
</Skeleton>

Loading

Loaded

403020100MonTueWedThuFriSatSun
Plate IVSeven bars, their axes and labels, where the chart will draw them.
05

A circle, if the data picks it.

Icons

An icon the data chooses (a status, a file type, a flag) becomes a 1px circle: a mark goes here, without guessing which. An icon that's always the same, like the clock next to "Updated", is design, and shows as itself.

Loading

  • Status
  • Updated 0 h ago

Loaded

  • Delivered
  • Updated 2 h ago
Plate VThe status icon comes from the data; the clock doesn't.
06

An outline.

Everything else

A data element with nothing inside to read, like a color swatch or a status dot, becomes a 1px outline of its own box. Every line in a skeleton is 1px, and every skeleton has its element's own corners: one line weight keeps a screen full of skeletons calm, and each keeps the shape of what it stands for.

Loading

Colors
Status

Loaded

Colors
In stock
Plate VISwatches and a status dot, outlined in their own shapes.
07

Estimate low.

How much

While loading, the component renders with invented placeholder data. Give it the short end of usual: short names, one-line titles, the fewest rows a list usually has. Real data can make the layout grow when it arrives, which is expected; it should never make it shrink, which looks like a glitch.

Loading

  • Name
  • Name
  • Name

Loaded

  • Marco Bellini
  • Hanna Lind
  • Jamal Okafor
  • Sofia Rossi
  • Daniel Cho
Plate VIIThree placeholder rows; five arrive, and the list grows.
08

A pulse, and nothing moves.

Motion

The skeletons pulse gently, and when the data arrives the bars fade out as it fades in. They're painted by CSS on the placeholder's own layout, rendered with the page: there from the first frame, before any JavaScript, and never jumping. With reduced motion, there's no pulse.

Title

Artist

00 songs

Plate VIIIReplay it: the pulse, then the data fading in.
09

Wrap what loads, nothing more.

Where

Each part that loads on its own gets its own skeleton, and hands over when its data arrives. While a part loads, it can't be clicked or read aloud: its values aren't real yet. Everything outside it works from the start.

Marigold

000 listeners

00 songs

Plate IXThe stats and the covers load on their own; Follow works all along.
10

Only for data that isn't there yet.

When not to

No skeleton over content that's already in the page: a post from a static build, text rendered on the server, a list the app already has while it refreshes. A skeleton over what's ready only delays it. A button that's saving shows its own loading state, and an upload shows its progress.

11

The rules together.

In an app

Three apps built with the boilerplate's components. Each loads its data in parts, the way real screens do. Press refresh in an app's toolbar to load it again.

A question of a usual length, long enough to wrap onto a second line.

An answer of a usual length, a few sentences long. It runs over two or three lines in the thread, about as long as a first reply.

A closing paragraph, a little shorter than the first one, saying what could come next.

A short follow-up question.

Plate XAn AI chat: the chat list, the thread and the account load; the composer is ready.

Overview

Revenue

000

+0.0%vs last month

Orders

000

+0.0%vs last month

Customers

000

+0.0%vs last month

Refund rate

000

+0.0%vs last month

Revenue

Daily, USD

Recent orders

  • Name Surname#0000$00.00Status
  • Name Surname#0000$00.00Status
  • Name Surname#0000$00.00Status
  • Name Surname#0000$00.00Status
Plate XIA dashboard: figures, trends, a chart and orders, each on its own time.

Recently played

Album

Artist

Album

Artist

Album

Artist

Album

Artist

Album

Artist

Artists you follow

Artist

Artist

Artist

Artist

Artist

Artist

Song

Artist

0:000:00
Plate XIIA music library: covers are plates, artists are circles, the player is ready.
12

Presets for common charts, any other on demand.

Chart drawings

The presets in @frontendsupply/chart-skeletons, loading. Each takes the chart's design size,width and height in pixels, and how many of its marks there will be: bars, points, slices, series. It fills the chart's box; the rest is the chart's own structure.

They're shortcuts, not the limit. For a chart that isn't here, ask for it by name, paste its code or a screenshot: the skill reads the chart, writes down its structure, and draws it with the same kit, checked like the presets.

pnpm add @frontendsupply/chart-skeletons
  • <LineChartSkeleton series={2} legend="bottom" />

  • <AreaChartSkeleton />

  • <BarChartSkeleton bars={7} />

  • <StackedBarChartSkeleton />

  • <HorizontalBarChartSkeleton bars={5} />

  • <PieChartSkeleton />

  • <DonutChartSkeleton />

  • <ScatterChartSkeleton />

  • <RadarChartSkeleton />

  • <HeatmapSkeleton rows={7} columns={12} />

  • <CandlestickChartSkeleton />

  • <FunnelChartSkeleton stages={4} />

  • <GaugeSkeleton />

  • <SparklineSkeleton />

Plate 13The fourteen presets, each filling its card. Nothing is measured.
13

Install once per project, then ask.

Getting started

Install the skeleton skill in your project's folder. It works in Claude Code, Codex, Cursor and other agents:

npx skills add frontendsupply/skills --skill skeleton

Add -g to install it for every project on your machine. Then ask, in your own words:

Show a skeleton while the orders table loads.

Or give it a chart, by name or as a screenshot:

Make a skeleton for the revenue chart in this screenshot.

Or have it replace skeletons drawn by hand:

Replace our hand-drawn skeletons with ones made from the components.

It needs React 19 and Tailwind CSS v4, and is built on Base UI and cn, which the skill installs if they're missing.

14

One variable.

Color

The skeletons take their color from your theme. The skill points it at your tokens:

:root {
  --skeleton: #e5e5e5; /* bars, borders and stripes */
}
15

Or just ask.

Commands

/skeleton
What loads in the project and how each screen shows it now. Changes nothing.
/skeleton add orders
Gives a component skeletons: marks its data, writes its placeholder data, wraps it.
/skeleton chart revenue
Draws a chart's skeleton at its size, from its name, its code or a screenshot.
/skeleton refactor
Replaces spinners and hand-drawn skeletons with skeletons drawn from the component.
/skeleton check
Checks the installed component (below).
16

Paint, never layout.

The check

A script reads your copy of the component and fails any class that turns on while loading and could move a box: the skeletons change only paint, so the placeholder's layout stays as it is under them. It also checks the color is set and Base UI and cn are in place. A second script checks every chart drawing: its viewBox and scaling, only the four parts, lines that stay 1px, no colors, everything inside the box and on the pixel grid. Then the skill opens the screen and looks at it, on desktop and on a phone.