Content Placeholder Pulse
Placeholder blocks rise and fall together on one slow cadence, so the region reads as dormant rather than busy.
The animated component in this preview is rendered from the canonical file shown here. The surrounding demo shell only provides context and is not part of the copied code.
import type { CSSProperties } from "react";
import { motion, useReducedMotion } from "motion/react";
/**
* Vibary · Content Placeholder Pulse
*
* Placeholder blocks that breathe in unison on one slow cadence. The
* whole group is driven by a single opacity animation on the wrapperAbout this pattern
The quietest waiting state in the library, and the one to reach for when the wait might be long. Every block is driven by a single opacity cycle on their shared wrapper, not one animation each: offset blocks read as a sweep and blocks that drift out of phase read as a fault, whereas a group that rises and falls as one reads as a single surface holding its place. The cadence is deliberately slow — around two seconds for a full breath — because this loops for the entire request and anything brisker starts pulling the eye back every time it comes around. Opacity is the only property in play; a placeholder that grows and shrinks promises the real content will do the same, and it will not.
Where it shows up
Screens we drew to show where this motion usually sits. Illustrations, not captures of any product.
- Chat thread
Channel and profile panes hold softly fading blocks while their data is fetched.
Related patterns
- Shimmer SweepA soft highlight travels across placeholder blocks, each one a beat behind the last.
- Skeleton to ContentBreathing placeholders hand off to the real content in one cross-fade and a small lift.
- Background Refresh HintA two-pixel tinted band travels the panel's top edge while data refetches, without interrupting reading.