shadcn.io is not affiliated with official shadcn/ui
Concentric rings around the centre breathe in and out, each a moment after the one inside it, so a soft pulse runs outward. The rings spread from a small one in the middle to past the container's corners, each a thin rim with a fill that deepens toward it, so the middle is the brightest and the rings fade as they go, melting into the page. It makes a good stage for a logo, an avatar or a short headline. It's pure CSS: one keyframe scales each ring, delayed by its place in the stack.
Use it for voice and call states, "live" indicators, or a hero with one centred message. For rings that turn instead of breathe, use Circles; for ripples from changing spots across the surface, Drops; for a beam sweeping over range rings, Sonar.
Installation
Usage
import { Ripple } from "@/components/ui/ripple";The rings sit behind whatever you put inside, centred in the container. Give the container a height; for the whole page, className="fixed inset-0 -z-10" with no children.
<Ripple className="flex min-h-[420px] items-center justify-center">
<h1 className="text-4xl font-semibold">Always listening</h1>
</Ripple>Demos
Avatar
size={96} starts the rings small enough to sit just outside a round avatar, for a "calling…" state in a profile card; the rest spread out to the card's corners.
Color
color="var(--primary)" tints the rings with your theme's primary colour, count={12} adds rings and intensity="strong" makes the innermost one stronger.
Accessibility
The rings are decorative: they're hidden from screen readers and never take the pointer, and your content stays on top in normal flow. With reduced motion the rings rest at full size, a still set of concentric discs. Nothing flashes. The middle, where the discs overlap, is at most about 15% of the ring colour at the default intensity, so text in your foreground colour keeps its contrast; check it if you pass intensity="strong" with a dark colour.
FAQ
How do I make it bigger or smaller?
size is the innermost ring's diameter in pixels (210). The outermost ring always passes the container's corners, and the rest spread out evenly between, so the rings fill a small card and a full page alike.
How many rings can I have?
count sets them, from 2 to 16 (8 by default). Opacity falls from the innermost ring to a sixth of it at the last, so any count fades out cleanly.
How does the stagger work?
Each ring starts its breath 3% of a cycle after the one inside it, so the pulse travels outward, and the outer rings breathe a little less deeply, so the large ones move as gently as the small. speed changes the cycle (2 seconds at 1) and the stagger with it.
Can I change the colour?
color takes any CSS colour or theme variable for the rim, the fill and the glow. By default it's your theme's --foreground, so it reads as grey on light pages and white on dark ones.
API Reference
Ripple
<div> data-slot="ripple"
color?string
The rings' colour, any CSS colour: their rims, faint fill and glow. By default your theme's foreground colour.
count?number
How many rings, from 2 to 16, spread evenly from the innermost out past the corners; they fade toward the last.
- Default
8
fade?"none" | "radial" | "top" | "bottom"
Where the rings fade out: toward the edges, the top, the bottom, or nowhere.
- Type
"none" | "radial" | "top" | "bottom"- Default
"radial"
intensity?"subtle" | "medium" | "strong"
How strongly the innermost ring shows. @default "medium".
- Type
"subtle" | "medium" | "strong"
size?number
The innermost ring's diameter, in pixels; the outermost always passes the corners, so the rest spread out between.
- Default
210
speed?number
How fast the rings breathe: 1 is a breath every 2 seconds, 2 twice as fast.
- Default
1
render?ReactElement | ((props: object, state: object) => ReactElement)
Replace the host element or compose it with another component.
- Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string
Merged with the part's classes.
--ripple-colorstring
The rings' colour (--foreground).
--ripple-opacitystring
The innermost ring's opacity (0.42).
--ripple-sizestring
The innermost ring's diameter (210px).
--ripple-speedstring
How fast the rings breathe, a multiplier (1).
Related
- Pro


Circles Background
LightRings that turn instead of breathe
- Pro


Drops Background
WavesRipples from random points across the surface
- Pro


Sonar Background
TechA sweep over range rings
- Pro


Portal Background
LightRings travelling out of a vanishing point
- Pro


Spotlight Background
LightLight pouring down from above instead of rings
- Pro


Interference Background
GenerativeTwo sources whose ripples cross