Stars Background
A minimalist animated stars background component for React. It creates a smooth and subtle starfield animation behind your content, perfect for landing pages, portfolios, or any section that needs a cosmic touch.
Bundui Components
Installation
Install the following dependencies:
npm i motion clsx tailwind-merge
Add utils file
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
Copy and paste the following code into your project:
"use client";
import * as React from "react";
import {
type HTMLMotionProps,
motion,
type SpringOptions,
type Transition,
useMotionValue,
useSpring,
} from "motion/react";
import { cn } from "@/lib/utils";
type StarLayerProps = HTMLMotionProps<"div"> & {
count: number;
size: number;
transition: Transition;
starColor: string;
};
function generateStars(count: number, starColor: string) {
const shadows: string[] = [];
for (let i = 0; i < count; i++) {
const x = Math.floor(Math.random() * 4000) - 2000;
const y = Math.floor(Math.random() * 4000) - 2000;
shadows.push(`${x}px ${y}px ${starColor}`);
}
return shadows.join(", ");
}
function StarLayer({
count = 1000,
size = 1,
transition = { repeat: Infinity, duration: 50, ease: "linear" },
starColor = "#fff",
className,
...props
}: StarLayerProps) {
const [boxShadow, setBoxShadow] = React.useState<string>("");
React.useEffect(() => {
setBoxShadow(generateStars(count, starColor));
}, [count, starColor]);
return (
<motion.div
data-slot="star-layer"
animate={{ y: [0, -2000] }}
transition={transition}
className={cn("absolute top-0 left-0 w-full h-[2000px]", className)}
{...props}
>
<div
className="absolute bg-transparent rounded-full"
style={{
width: `${size}px`,
height: `${size}px`,
boxShadow: boxShadow,
}}
/>
<div
className="absolute bg-transparent rounded-full top-[2000px]"
style={{
width: `${size}px`,
height: `${size}px`,
boxShadow: boxShadow,
}}
/>
</motion.div>
);
}
type StarsBackgroundProps = React.ComponentProps<"div"> & {
factor?: number;
speed?: number;
transition?: SpringOptions;
starColor?: string;
};
export function StarsBackground({
children,
className,
factor = 0.05,
speed = 50,
transition = { stiffness: 50, damping: 20 },
starColor = "#fff",
...props
}: StarsBackgroundProps) {
const offsetX = useMotionValue(1);
const offsetY = useMotionValue(1);
const springX = useSpring(offsetX, transition);
const springY = useSpring(offsetY, transition);
const handleMouseMove = React.useCallback(
(e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
const centerX = window.innerWidth / 2;
const centerY = window.innerHeight / 2;
const newOffsetX = -(e.clientX - centerX) * factor;
const newOffsetY = -(e.clientY - centerY) * factor;
offsetX.set(newOffsetX);
offsetY.set(newOffsetY);
},
[offsetX, offsetY, factor],
);
return (
<div
data-slot="stars-background"
className={cn(
"relative size-full overflow-hidden bg-[radial-gradient(ellipse_at_bottom,_#262626_0%,_#000_100%)]",
className,
)}
onMouseMove={handleMouseMove}
{...props}
>
<motion.div style={{ x: springX, y: springY }}>
<StarLayer
count={1000}
size={1}
transition={{ repeat: Infinity, duration: speed, ease: "linear" }}
starColor={starColor}
/>
<StarLayer
count={400}
size={2}
transition={{
repeat: Infinity,
duration: speed * 2,
ease: "linear",
}}
starColor={starColor}
/>
<StarLayer
count={200}
size={3}
transition={{
repeat: Infinity,
duration: speed * 3,
ease: "linear",
}}
starColor={starColor}
/>
</motion.div>
{children}
</div>
);
}
API
Prop | Type | Default | Description |
---|---|---|---|
children | React.ReactNode | The content to be wrapped inside the background component. | |
className | string | undefined | Optional Tailwind/CSS classes for custom styling on the outer container. |
factor | number | 0.05 | Controls the intensity of the parallax effect. |
speed | number | 50 | Speed of the star animation. |
transition | SpringOptions | { stiffness: 50, damping: 20 } | Spring transition options for mouse movement. |
starColor | string | "#fff" | Color of the stars in the background. |