Spotlight Card
A card whose border and background glow follow the pointer.
interaction
01 / spotlight
Move your cursor here
A border and glow follow your pointer, using CSS variables only.
components/sidd-ui/spotlight-card.tsx
"use client"
import { cn } from "cn"
import { useRef } from "react"
export function SpotlightCard({
children,
color = "rgba(56, 189, 248, 0.35)",
size = 280,
className,
}: {
children: React.ReactNode
color?: string
size?: number
className?: string
}) {
const ref = useRef<HTMLDivElement>(null)
return (
<div
ref={ref}
onPointerMove={(e) => {
const el = ref.current
if (!el) return
const rect = el.getBoundingClientRect()
el.style.setProperty("--x", `${e.clientX - rect.left}px`)
el.style.setProperty("--y", `${e.clientY - rect.top}px`)
}}
className={cn("group bg-border relative overflow-hidden rounded-xl p-px", className)}
style={{ "--spot": color, "--size": `${size}px` } as React.CSSProperties}
>
<div
className="pointer-events-none absolute inset-0 opacity-0 transition-opacity duration-300 group-hover:opacity-100"
style={{
background:
"radial-gradient(var(--size) circle at var(--x, 50%) var(--y, 50%), var(--spot), transparent 70%)",
}}
aria-hidden
/>
<div className="bg-background relative h-full rounded-[11px]">
<div
className="pointer-events-none absolute inset-0 rounded-[inherit] opacity-0 transition-opacity duration-300 group-hover:opacity-40"
style={{
background:
"radial-gradient(calc(var(--size) * 0.8) circle at var(--x, 50%) var(--y, 50%), var(--spot), transparent 70%)",
}}
aria-hidden
/>
<div className="relative">{children}</div>
</div>
</div>
)
}
Features
- Pointer position is written to CSS variables, so React never re-renders on move.
- Glow shows on both the 1px border and the background.
- Configurable color and spotlight size.
Why I built this
I like interfaces that respond to you before you click. A light that follows the cursor makes a static grid of cards feel tactile.
Most versions I found re-rendered on every mouse move. Keeping it in CSS variables made it smooth and simple.
Usage
example.tsx
<SpotlightCard color="rgba(56,189,248,.35)">...</SpotlightCard>