Skip to content

Flow Field

Add streaks drifting on a smooth current that the pointer stirs into a vortex.

import { FlowField } from '@youj/motion/backgrounds'

Experimental: what this label means

Installation & usage

npm i @youj/motion

For an app already set up with npx @youj/cli init, which installs the peers (@youj/core, @youj/motion, motion and Base UI) and wires the provider. New app? Start at Installation.

Use it where the idea is movement: traffic, data in flight, networks, anything that should feel alive and directed. It reads as weather over the page, and it answers the pointer without asking anything of it. Don't use it behind reading-length text, since the streaks cross everything, and keep it to one animated background per page.

The field fills its nearest positioned ancestor and paints behind your content, so make the container relative and isolate.

import { FlowField } from '@youj/motion/backgrounds'

export function CurrentHero() {
  return (
    <section className="relative isolate min-h-[560px]">
      <FlowField />
      <p className="relative text-5xl font-semibold">Watch requests find their way</p>
    </section>
  )
}

Each streak rides a smooth noise current, so neighbors flow the same way and the direction changes slowly across the canvas and over time. A streak lives for a few seconds: it fades in, drifts, fades out and starts again somewhere else. The number of streaks follows the area: at density={1}, one per 3,200 square pixels, capped at 800. A phone and a wide display look equally full.

Reference

Propscolors, intensity, speed… (8)

Props

FlowField props
PropType
colors[streaks: string, highlight: string]

[streaks, highlight] CSS colors. Default: --color-fg-muted, --color-accent.

–
intensitynumber

Opacity of the streaks, 0–1.5.

default 1

1
speednumber

Current speed multiplier.

default 1

1
densitynumber

Streaks per area, relative. 1 ≈ one streak per 3 200 CSS px².

default 1

1
trailnumber

Trail length multiplier, 0.3–1.5.

default 1

1
scalenumber

Size of the swirls in the current: above 1 is broader and calmer, below 1 is busier.

default 1

1
interactiveboolean

Pointer reactivity: the pointer stirs a vortex in the current.

default true

true
classNamestring–
PerformanceIt's drawn with Canvas 2D, not WebGL

Performance

It's drawn with Canvas 2D, not WebGL. Each frame redraws every trail from a short history, in a handful of strokes batched by opacity, so nothing is left behind on the canvas and a resize or a theme change is exact. The canvas renders at a device-pixel ratio capped at 2, and the low motion budget keeps 60% of the streaks. The loop pauses when the field is offscreen or the tab is hidden, and it stops and cleans up on unmount. If the browser can't create a 2D context, it falls back to a static CSS wash of the highlight color.

MotionCurrent, vortex, streak life · reduced motion

Motion

Motion tokens
MomentTokens
Currenta smooth noise field that shifts slowly over time
no token

speed ÷ time scale

speed ÷ time scale
Vortexthe current curls around the pointer within reach
no token

per-frame physics

per-frame physics
Pointer strengtheases in and out with the pointer
no token

smoothed per frame

smoothed per frame
Streak lifefades in, drifts, fades out and respawns
no token

4 to 10 seconds

4 to 10 seconds

Reduced motion

Draws one fixed, seeded field with its trails laid down: the same composition every time. There's no drift and no pointer response, and it redraws only when the size, the props or the theme change.

Reduced motion

The field shows a fixed composition from a seeded layout, so it's the same on every visit and in every screenshot. The streaks and trails keep their colors and density. Only the drift and the pointer response are gone. Switch on Reduced motion in any preview above to compare.

AccessibilityARIA

Accessibility

  • It's decorative: the element is aria-hidden and ignores pointer events.
  • Streaks cross whatever sits above them. Keep a quiet pool of canvas behind the copy, as the hero preview does, or lower intensity, and check your text's contrast there.
  • The drift is slow and stops offscreen. Under reduced motion the field doesn't move at all.