Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Backgrounds

Pro

Spotlight Background for React

Stage lights that shine down into a section from above it: soft cones of light that sweep slowly and cross, with dust in the beams and pools of light on the floor. For React with Base UI, when a hero, a launch or a pricing block should feel like it's on stage.

Framework

Stage lights shine down into the section from just above it: soft cones of light that sweep slowly and cross, with dust drifting in each beam and a pool of light where it meets the floor. Each cone is a still, blurred shape turned about its source, its dust slides down the beam and its pool slides along the floor in step, so everything moves with CSS transforms that the browser composites without repainting. On a light page the surface takes a soft grey gradient so the warm light reads; on a dark one the cones add up where they cross.

Use it behind a hero, a launch or a pricing block that should feel like it's on stage. For light that drifts with no source, use Aurora; for a sun pouring in from an edge, Corona; for thin streaks of light, Beams; for coloured light from a turning ball, Disco.

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 { Spotlight } from "@/components/ui/spotlight";
<Spotlight className="flex min-h-[32rem] items-center justify-center">
  <h1 className="text-5xl font-semibold">Bring your work into the light</h1>
</Spotlight>

Spotlight is a container: whatever you put inside sits on top of the light, in normal flow. The lights hang just above the top edge and the pools sit on the bottom edge, so the cones fill the whole box at any size; wider boxes get wider cones. Give it a height or content. For a backdrop behind the whole page, render it empty with className="fixed inset-0 -z-10".

Demos

Colors

colors takes up to three CSS colours, one per light, repeated when there are fewer; here magenta, cyan and amber at intensity="strong", on a scene that stays dark. Where the cones cross, the colours add up like light.

Preview width

Follow the pointer

interactive adds one more light from the top centre that fades in when the pointer arrives, turns to follow it and lights a pool under it; when the pointer leaves, it fades out where it was. count={1} leaves a single sweeping light from the top left, which suits a card.

Preview width

Accessibility

The light is decoration: it's hidden from assistive tech and lets every click through to your content, so links and buttons on top keep working. With reduced motion the lights hold still where they are, and the pointer's light stays off. Nothing flashes, and touch drags don't move the pointer's light, so scrolling on a phone stays smooth.

Put copy over it in your foreground colour (text-foreground). At the default intensity the brightest crossing keeps it above 4.5:1 in both colour schemes; with intensity="strong" on a dark surface, keep small text out of the spot where the cones cross.

FAQ

How is it built?

Each light is a cone hung just above the top edge: a still, blurred shape (a data-URI mask in your stylesheet) turned about its source with rotate. Its dust drifts down the beam by one tile, and its pool slides along the floor on the same timing, with translate. Nothing repaints and no script runs while it moves.

How many lights can I have?

count takes 1, 2 or 3 (3 by default): one from the top left, two from the top corners that cross, or those two with a fainter one in the middle. interactive adds one more that follows the pointer.

How does the pointer's light follow the pointer?

A pointer handler works out the angle from the light's source and writes it, with the position, as CSS variables on that light; a CSS transition eases it there, so nothing re-renders. The first move lands at once and the next ones glide.

Can I change the colours?

Pass up to three colors, one per light, as any CSS colours, such as var(--primary). By default it's a warm white, with a soft grey surface behind it in light mode so the light shows.

How do I make it slower or faster?

speed multiplies the sweep: at 1 each light swings in 19 to 29 seconds, at 2 twice as fast. intensity sets how strongly the lights show.

How do I put it behind the whole page?

Render it empty with className="fixed inset-0 -z-10". To light one section, wrap its content and give it a height, such as min-h-svh.

Does it respect reduced motion?

Yes: the lights, their dust and their pools hold still, and the pointer's light never shows.

API Reference

Spotlight

<div> data-slot="spotlight"

PropType
colors?string[]

Up to three CSS colors, one per light, repeated when there are fewer. By default a warm white.

count?1 | 2 | 3

How many lights shine from above: one from the top left, two from the top corners, or three with a fainter one in the middle.

Type
1 | 2 | 3
Default
3
intensity?"subtle" | "medium" | "strong"

How strongly the lights show. @default "medium".

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

Whether one more light, from the top centre, turns to follow the pointer and lights a pool under it.

Default
false
speed?number

How fast the lights sweep, as a multiplier: each swing takes 19 to 29 seconds at 1, half as long at 2.

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
--spotlight-colorstring

A light's color (a warm white).

--spotlight-speedstring

How fast the lights sweep, a multiplier (1).

All 100 backgrounds