Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Backgrounds

Pro

Magnetic Field Background for React

Iron filings lined up along the field of alternating poles, with traced field lines, and the pointer as one more pole. For React with Base UI, when a science, hardware or developer-tool page needs a field that reacts but costs nothing at rest.

Framework

Magnetic Field draws short iron filings lined up along the field of four poles on a ring, north and south in turn, with field lines traced out of each pole and arcing to its neighbours. The ring is an oval stretched to the box, so a wide banner, a tall phone hero and a card are all filled with curving structure, and the filings are spread evenly, as many per area at any size. Filings are darker where the field is strong, so the poles stand out. The pointer is a fifth pole: move it over the box and every filing turns to follow.

The field stays still until the pointer moves, so it costs nothing at rest; set speed to turn the ring slowly. It suits science, hardware and developer-tool pages. For streaks that ride a flow, use Vortex, which spirals into a calm eye, or Wind; for contour lines with the same textbook feel, Topography. It's a small canvas that redraws only when something changes and draws the field once with reduced motion.

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 { MagneticField } from "@/components/ui/magnetic-field";
<MagneticField className="min-h-[480px]">
  <h1 className="text-5xl font-semibold">Ship faster</h1>
</MagneticField>

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

Demos

Filings only

fieldLines={false} leaves only the filings; 3,600 of them per 1440×900 at filingLength={9} give the classic photo of iron filings on paper.

Preview width

Orbit

speed={1} turns the ring of poles once in about two and a half minutes, so the field slowly reshapes on its own, and polarity="south" makes the pointer a south pole, which the filings point toward.

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 the field once and ignores the pointer, and the poles hold still whatever speed says. The filings are low contrast, and the darkest ones sit at the poles on the ring, away from the centre, where the fields cancel and the filings are faintest, so a centred headline in text-foreground stays readable. Nothing flashes: the field changes only as fast as the pointer moves.

FAQ

How is the field computed?

Each pole adds a pull that weakens with the square of the distance, with alternating signs around the ring. The poles sit on an oval at 34% of the width and 31% of the height from the centre, so the field stretches with the box. Every filing points along the sum where it lies and is darker where the field is strong; the field lines follow the same sum in 6 px steps, and stop where the poles' fields cancel out.

How does the pointer change it?

It's an extra pole. intensity sets its strength against the fixed poles, polarity makes it north or south, and interactive={false} turns it off. Touch never adds a pole, so scrolling on a phone isn't disturbed.

Does it animate on its own?

Not by default: it redraws only when the pointer moves or the size or theme changes. Set speed above 0 and the ring of poles turns slowly, redrawn every frame while it's on screen.

Can I hide the field lines?

Yes, fieldLines={false} leaves only the filings. Raise count (filings per 1440×900 box, 1,800 by default) and shorten filingLength for a denser look; poleCount changes how many poles sit on the ring.

Is it heavy?

One redraw, about 1,300 filings at 1280×720 and 48 traced lines, takes a fraction of a millisecond, and nothing runs while the field is at rest or offscreen.

How do I change the colors?

filingColor and lineColor take any CSS color; by default they're the theme's muted text color and primary color, so the field follows light and dark mode. The lines are drawn at 25% opacity.

API Reference

MagneticField

<div> data-slot="magnetic-field"

PropType
count?number

How many iron filings in a 1440×900 box; other sizes get as many per area, never more than 4,000.

Default
1800
fade?"none" | "radial" | "top" | "bottom"

Where the field fades out: toward every edge from the centre (radial), toward the top, or toward the bottom. It's a mask, so the field fades into whatever is behind it.

Type
"none" | "radial" | "top" | "bottom"
Default
"radial"
fieldLines?boolean

Field lines traced out from each pole. @default true.

Default
true
filingColor?string

The filings' color, any CSS color. @default "var(--muted-foreground)".

filingLength?number

Each filing's length, in pixels. @default 14.

Default
14
intensity?"subtle" | "medium" | "strong"

How strong the pointer's pole is against the fixed ones. @default "medium".

Type
"subtle" | "medium" | "strong"
Default
"medium"
interactive?boolean

Whether the pointer acts as an extra pole. @default true.

Default
true
lineColor?string

The field lines' color, any CSS color, drawn at 25% opacity. @default "var(--primary)".

polarity?"north" | "south"

The pointer pole's sign: filings point away from a north pole. @default "north".

Type
"north" | "south"
Default
"north"
poleCount?number

How many poles sit on the ring, alternating north and south (1 to 8). The ring is an oval stretched to the box, so wide and tall boxes fill.

Default
4
speed?number

How fast the ring of poles turns: 0 holds it, 1 turns once in about 150 s. @default 0.

Default
0
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
--magnetic-field-colorstring

The filings' color (--muted-foreground).

--magnetic-field-line-colorstring

The field lines' color (--primary).

All 100 backgrounds