Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Backgrounds

Pro

Vortex Background for React

A whirlpool of fine colored streaks spiraling into a calm eye and filling the whole container. For React with Base UI, when a hero or a launch page needs deep, hypnotic motion behind its headline.

Framework

Vortex fills its container with fine streaks that circle an eye: fast close to it, slow far out, each drifting gently inward along a spiral. The speed difference shears the field into long arcs that keep re-forming, the brighter streaks gather on two slowly turning spiral arms, and a faint glow sits under the eye. Streaks grow out of nothing, then shrink away into the calm eye or at the end of their life, so nothing pops. They're pink near the eye, violet half-way out and indigo at the edges, deeper on a light page and brighter on a dark one.

It's a small canvas with no package, paused offscreen, and it covers the whole box at any size or shape: the eye can sit anywhere with centerX and centerY. For straight streamlines across the area use Wind; for a funnel seen from the side, Tornado; for a soft band of color without particles, Aurora.

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Usage

import { Vortex } from "@/components/ui/vortex";
<Vortex className="min-h-[480px]">
  <h1 className="text-5xl font-semibold">Ship faster</h1>
</Vortex>

Vortex is a container: give it a size, put your content inside, and the streaks swirl behind it. For a background behind the whole page, pass className="fixed inset-0 -z-10" and no children.

Demos

Theme colors, eye to the side

colors takes up to three CSS colors, from the eye outward, repeated when there are fewer. Theme tokens, here var(--primary) and var(--muted-foreground), give an ink-like version that follows light and dark mode. centerX={0.78} moves the eye toward the end edge, leaving calm space for a headline at the start.

Preview width

Interactive

With interactive, the pointer stirs a small whirl of its own: streaks within 160 px of it curl around it as they pass. This card uses the most streaks, count={1500}, at speed={0.7}.

Preview width

Accessibility

The canvas is decoration: it's hidden from assistive tech and never takes the pointer, so your content is read and clicked as usual. With reduced motion it draws one frame, trails included, and ignores the pointer. The eye itself is calm and the streaks are thin, so a centered headline in text-foreground reads well over them; keep long body copy short or on a surface, where the arms are busiest. Nothing flashes: every streak grows in and shrinks away.

FAQ

What moves the streaks?

Each streak circles the eye at a speed that peaks a little way out and falls off toward the edges, and it drifts inward at a fixed share of that speed, so its path is a spiral. A slow wobble bends the flow so the arcs never look ruled. The near, brighter streaks are born on two spiral arms that follow the flow and turn slowly, which gives the whirl its shape.

Does it fill wide or tall boxes?

Yes. The streaks are spread over the whole box and the spin reaches every corner, whatever the shape: a 1440×360 banner, a phone hero or a card. count is how many there are in a 1440×900 box; other sizes get as many per area, and small boxes a few more so they never look sparse.

Can I move the eye?

centerX and centerY place it, as shares of the box from 0 to 1. centerX counts from the start edge, so it mirrors in right-to-left pages. Put the eye to one side of a split hero, or low in the box to frame a headline above it.

How do I change the colors?

colors takes up to three CSS colors, from the eye outward. By default they're a pink, violet and indigo tuned separately for light and dark mode; pass theme tokens for a monochrome look, or set --vortex-color-1 to --vortex-color-3 in your CSS. The glow under the eye follows them.

How are the trails made?

Each streak keeps its last few positions and draws them as a short tail that fades toward the end, in two widths for depth. The canvas is cleared every frame, so nothing smears or lingers, and the tails keep their length at 60 or 120 Hz and at any speed.

Does it react to the pointer?

Only with interactive: streaks near the pointer curl around it. It's off by default, and touch never stirs them, so scrolling on a phone isn't disturbed.

Is it heavy?

No: a frame costs well under half a millisecond at 1280×720, with no canvas filters, and the loop stops when the background scrolls out of view or the tab is hidden.

API Reference

Vortex

<div> data-slot="vortex"

PropType
centerX?number

Where the eye sits across the box, from the start edge: 0 to 1. @default 0.5.

Default
0.5
centerY?number

Where the eye sits down the box: 0 (top) to 1 (bottom). @default 0.5.

Default
0.5
colors?string[]

Up to three CSS colors, from the eye outward, taken in turn and repeated when there are fewer.

Default
pink, violet and indigo, tuned for light and dark
count?number

How many streaks in a 1440×900 box; other sizes get as many per area, never more than 1,500.

Default
1200
interactive?boolean

Whether the pointer stirs a small whirl of its own. @default false.

Default
false
size?number

Scales the streaks' width: 0.8 and 1.5 px at 1. @default 1.

Default
1
speed?number

Multiplies the spin; 0 holds the streaks still. @default 1.

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.

CSS variableType
--vortex-color-1string

The streaks' color by the eye (pink).

--vortex-color-2string

Their color half-way out (violet).

--vortex-color-3string

Their color far out (indigo).

All 100 backgrounds