A skeleton screen expresses the structure of content about to arrive
Aliases: placeholder UI · grey-block loading · content placeholder
What it is
A skeleton screen lays out low-contrast blocks in the places upcoming content will occupy: a bar for a title, a circle for an avatar, a few lines for body. It is not a spinner and not a progress bar. A spinner says “still waiting.” A skeleton says “what you are waiting for has this structure, and it will take these positions.” Its working window is the stretch when content is about to arrive and the structure is already known. If the structure is still unknown, drawing a skeleton is guessing—which is the next leaves.
Why it happens
During a wait people ask two things: is it still working, and what is coming. A spinner answers the first. A skeleton answers the second by rehearsing the layout, so vision partitions the region into “title will be here / list will be here / image will be here” before the data lands. That rehearsal cuts the orientation cost when content arrives: gaze is already on the future title, and does not have to search again once real type appears. A skeleton also rescues blankness from being read as “broken” or “nothing here.” It depends on a predictable structure: a card list, a profile header, an article body—templates that exist before the payload. Unpredictable structure cannot be rehearsed, and the skeleton becomes a draft of a lie.
Studying it
Hold one wait constant and compare blank screen, spinner, and skeleton, then measure time to find a target after content arrives.
Independent variables: how well the skeleton matches the final layout, wait duration, content type (list / article / dashboard). Dependent variables: subjective wait, time to first-locate the target after arrival, and whether the skeleton is mistaken for already-loaded but damaged content.
Lab participants who know “this is loading” rarely treat grey blocks as broken body text. In a product the sharper risk is a skeleton that stays so long people start tapping the blocks. Log those mis-taps, not only “did it feel fast.”
Where it stops holding
Pages whose structure varies by user (a custom dashboard, modules that depend on permission) cannot honestly rehearse before data returns; the skeleton will promise blocks that are not there. On a very short wait a skeleton that flashes is noisier than showing nothing—that timing belongs with loading indicators. A skeleton expresses structure, not progress; painting the blocks left-to-right as if they were a percent is a different, false claim. For screen readers the skeleton usually has no equivalent; there must be a separate “loading” state, not an assumption that grey blocks were heard.
Applying it
- Use a skeleton only when the template is known: list rows, a profile header, an article column, drawn on the real grid, not a generic wave.
- Make block kinds readable (image, title, row); do not ship abstract rectangles that map to no control.
- When loading ends, let real content take the skeleton’s coordinates so the structural promise is cashed.
- Verify by overlaying a skeleton screenshot on the first loaded frame. If major blocks miss, the skeleton was not expressing the structure about to arrive.