Sparkles
Magical particle animations that bring websites to life. This interactive React component creates captivating sparkle effects perfect for Next.js applications requiring enchanting visual elements.
Powered by
import React from "react";import { SparklesCore } from '@/components/ui/shadcn-io/sparkles';const Example = () => { return ( <div className="h-[40rem] w-full bg-black flex flex-col items-center justify-center overflow-hidden rounded-md"> <h1 className="md:text-7xl text-3xl lg:text-9xl font-bold text-center text-white relative z-20"> Acme </h1> <div className="w-[40rem] h-40 relative"> {/* Gradients */} <div className="absolute inset-x-20 top-0 bg-gradient-to-r from-transparent via-indigo-500 to-transparent h-[2px] w-3/4 blur-sm" /> <div className="absolute inset-x-20 top-0 bg-gradient-to-r from-transparent via-indigo-500 to-transparent h-px w-3/4" /> <div className="absolute inset-x-60 top-0 bg-gradient-to-r from-transparent via-sky-500 to-transparent h-[5px] w-1/4 blur-sm" /> <div className="absolute inset-x-60 top-0 bg-gradient-to-r from-transparent via-sky-500 to-transparent h-px w-1/4" /> {/* Core component */} <SparklesCore background="transparent" minSize={0.4} maxSize={1} particleDensity={1200} className="w-full h-full" particleColor="#FFFFFF" /> {/* Radial Gradient to prevent sharp edges */} <div className="absolute inset-0 w-full h-full bg-black [mask-image:radial-gradient(350px_200px_at_top,transparent_20%,white)]"></div> </div> </div> );};export default Example;
"use client";import React, { useId, useMemo } from "react";import { useEffect, useState } from "react";import Particles, { initParticlesEngine } from "@tsparticles/react";import type { Container, SingleOrMultiple } from "@tsparticles/engine";import { loadSlim } from "@tsparticles/slim";import { cn } from "@/lib/utils";import { motion, useAnimation } from "framer-motion";type ParticlesProps = { id?: string; className?: string; background?: string; particleSize?: number; minSize?: number; maxSize?: number; speed?: number; particleColor?: string; particleDensity?: number;};export const SparklesCore = (props: ParticlesProps) => { const { id, className, background, minSize, maxSize, speed, particleColor, particleDensity, } = props; const [init, setInit] = useState(false); useEffect(() => { initParticlesEngine(async (engine) => { await loadSlim(engine); }).then(() => { setInit(true); }); }, []); const controls = useAnimation(); const particlesLoaded = async (container?: Container) => { if (container) { controls.start({ opacity: 1, transition: { duration: 1, }, }); } }; const generatedId = useId(); return ( <motion.div animate={controls} className={cn("opacity-0", className)}> {init && ( <Particles id={id || generatedId} className={cn("h-full w-full")} particlesLoaded={particlesLoaded} options={{ background: { color: { value: background || "#0d47a1", }, }, fullScreen: { enable: false, zIndex: 1, }, fpsLimit: 120, interactivity: { events: { onClick: { enable: true, mode: "push", }, onHover: { enable: false, mode: "repulse", }, resize: true as any, }, modes: { push: { quantity: 4, }, repulse: { distance: 200, duration: 0.4, }, }, }, particles: { bounce: { horizontal: { value: 1, }, vertical: { value: 1, }, }, collisions: { absorb: { speed: 2, }, bounce: { horizontal: { value: 1, }, vertical: { value: 1, }, }, enable: false, maxSpeed: 50, mode: "bounce", overlap: { enable: true, retries: 0, }, }, color: { value: particleColor || "#ffffff", animation: { h: { count: 0, enable: false, speed: 1, decay: 0, delay: 0, sync: true, offset: 0, }, s: { count: 0, enable: false, speed: 1, decay: 0, delay: 0, sync: true, offset: 0, }, l: { count: 0, enable: false, speed: 1, decay: 0, delay: 0, sync: true, offset: 0, }, }, }, effect: { close: true, fill: true, options: {}, type: {} as SingleOrMultiple<string> | undefined, }, groups: {}, move: { angle: { offset: 0, value: 90, }, attract: { distance: 200, enable: false, rotate: { x: 3000, y: 3000, }, }, center: { x: 50, y: 50, mode: "percent", radius: 0, }, decay: 0, distance: {}, direction: "none", drift: 0, enable: true, gravity: { acceleration: 9.81, enable: false, inverse: false, maxSpeed: 50, }, path: { clamp: true, delay: { value: 0, }, enable: false, options: {}, }, outModes: { default: "out", }, random: false, size: false, speed: { min: 0.1, max: 1, }, spin: { acceleration: 0, enable: false, }, straight: false, trail: { enable: false, length: 10, fill: {}, }, vibrate: false, warp: false, }, number: { density: { enable: true, width: 400, height: 400, }, limit: { mode: "delete", value: 0, }, value: particleDensity || 120, }, opacity: { value: { min: 0.1, max: 1, }, animation: { count: 0, enable: true, speed: speed || 4, decay: 0, delay: 0, sync: false, mode: "auto", startValue: "random", destroy: "none", }, }, reduceDuplicates: false, shadow: { blur: 0, color: { value: "#000", }, enable: false, offset: { x: 0, y: 0, }, }, shape: { close: true, fill: true, options: {}, type: "circle", }, size: { value: { min: minSize || 1, max: maxSize || 3, }, animation: { count: 0, enable: false, speed: 5, decay: 0, delay: 0, sync: false, mode: "auto", startValue: "random", destroy: "none", }, }, stroke: { width: 0, }, zIndex: { value: 0, opacityRate: 1, sizeRate: 1, velocityRate: 1, }, destroy: { bounds: {}, mode: "none", split: { count: 1, factor: { value: 3, }, rate: { value: { min: 4, max: 9, }, }, sizeOffset: true, }, }, roll: { darken: { enable: false, value: 0, }, enable: false, enlighten: { enable: false, value: 0, }, mode: "vertical", speed: 25, }, tilt: { value: 0, animation: { enable: false, speed: 0, decay: 0, sync: false, }, direction: "clockwise", enable: false, }, twinkle: { lines: { enable: false, frequency: 0.05, opacity: 1, }, particles: { enable: false, frequency: 0.05, opacity: 1, }, }, wobble: { distance: 5, enable: false, speed: { angle: 50, move: 10, }, }, life: { count: 0, delay: { value: 0, sync: false, }, duration: { value: 0, sync: false, }, }, rotate: { value: 0, animation: { enable: false, speed: 0, decay: 0, sync: false, }, direction: "clockwise", path: false, }, orbit: { animation: { count: 0, enable: false, speed: 1, decay: 0, delay: 0, sync: false, }, enable: false, opacity: 1, rotation: { value: 45, }, width: 1, }, links: { blink: false, color: { value: "#fff", }, consent: false, distance: 100, enable: false, frequency: 1, opacity: 1, shadow: { blur: 5, color: { value: "#000", }, enable: false, }, triangles: { enable: false, frequency: 1, }, width: 1, warp: false, }, repulse: { value: 0, enabled: false, distance: 1, duration: 1, factor: 1, speed: 1, }, }, detectRetina: true, }} /> )} </motion.div> );};
Installation
npx shadcn@latest add https://www.shadcn.io/registry/sparkles.json
npx shadcn@latest add https://www.shadcn.io/registry/sparkles.json
pnpm dlx shadcn@latest add https://www.shadcn.io/registry/sparkles.json
bunx shadcn@latest add https://www.shadcn.io/registry/sparkles.json
Features
- Interactive click-to-sparkle adding four new particles with realistic physics on user interaction
- Hardware-accelerated rendering maintaining smooth 60fps performance across all devices
- Flexible color customization supporting hex, RGB, or HSL values for brand matching
- Configurable particle density from subtle ambience (50 particles) to magical celebrations (300+)
- TypeScript support with complete type safety for reliable React development
- Mobile-optimized performance with automatic device detection and performance scaling
- tsParticles integration leveraging industry-leading particle engine for professional effects
- Framer Motion compatibility for seamless fade-in animations and motion preferences
Examples
Full Page Background
import React from "react";import { SparklesCore } from '@/components/ui/shadcn-io/sparkles';const Example = () => { return ( <div className="h-[40rem] relative w-full bg-slate-950 flex flex-col items-center justify-center overflow-hidden rounded-md"> <div className="w-full absolute inset-0 h-screen"> <SparklesCore id="tsparticlesfullpage" background="transparent" minSize={0.6} maxSize={1.4} particleDensity={100} className="w-full h-full" particleColor="#FFFFFF" speed={1} /> </div> <h1 className="md:text-7xl text-3xl lg:text-9xl font-bold text-center text-white relative z-20"> Build faster </h1> </div> );};export default Example;
"use client";import React, { useId, useMemo } from "react";import { useEffect, useState } from "react";import Particles, { initParticlesEngine } from "@tsparticles/react";import type { Container, SingleOrMultiple } from "@tsparticles/engine";import { loadSlim } from "@tsparticles/slim";import { cn } from "@/lib/utils";import { motion, useAnimation } from "framer-motion";type ParticlesProps = { id?: string; className?: string; background?: string; particleSize?: number; minSize?: number; maxSize?: number; speed?: number; particleColor?: string; particleDensity?: number;};export const SparklesCore = (props: ParticlesProps) => { const { id, className, background, minSize, maxSize, speed, particleColor, particleDensity, } = props; const [init, setInit] = useState(false); useEffect(() => { initParticlesEngine(async (engine) => { await loadSlim(engine); }).then(() => { setInit(true); }); }, []); const controls = useAnimation(); const particlesLoaded = async (container?: Container) => { if (container) { controls.start({ opacity: 1, transition: { duration: 1, }, }); } }; const generatedId = useId(); return ( <motion.div animate={controls} className={cn("opacity-0", className)}> {init && ( <Particles id={id || generatedId} className={cn("h-full w-full")} particlesLoaded={particlesLoaded} options={{ background: { color: { value: background || "#0d47a1", }, }, fullScreen: { enable: false, zIndex: 1, }, fpsLimit: 120, interactivity: { events: { onClick: { enable: true, mode: "push", }, onHover: { enable: false, mode: "repulse", }, resize: true as any, }, modes: { push: { quantity: 4, }, repulse: { distance: 200, duration: 0.4, }, }, }, particles: { bounce: { horizontal: { value: 1, }, vertical: { value: 1, }, }, collisions: { absorb: { speed: 2, }, bounce: { horizontal: { value: 1, }, vertical: { value: 1, }, }, enable: false, maxSpeed: 50, mode: "bounce", overlap: { enable: true, retries: 0, }, }, color: { value: particleColor || "#ffffff", animation: { h: { count: 0, enable: false, speed: 1, decay: 0, delay: 0, sync: true, offset: 0, }, s: { count: 0, enable: false, speed: 1, decay: 0, delay: 0, sync: true, offset: 0, }, l: { count: 0, enable: false, speed: 1, decay: 0, delay: 0, sync: true, offset: 0, }, }, }, effect: { close: true, fill: true, options: {}, type: {} as SingleOrMultiple<string> | undefined, }, groups: {}, move: { angle: { offset: 0, value: 90, }, attract: { distance: 200, enable: false, rotate: { x: 3000, y: 3000, }, }, center: { x: 50, y: 50, mode: "percent", radius: 0, }, decay: 0, distance: {}, direction: "none", drift: 0, enable: true, gravity: { acceleration: 9.81, enable: false, inverse: false, maxSpeed: 50, }, path: { clamp: true, delay: { value: 0, }, enable: false, options: {}, }, outModes: { default: "out", }, random: false, size: false, speed: { min: 0.1, max: 1, }, spin: { acceleration: 0, enable: false, }, straight: false, trail: { enable: false, length: 10, fill: {}, }, vibrate: false, warp: false, }, number: { density: { enable: true, width: 400, height: 400, }, limit: { mode: "delete", value: 0, }, value: particleDensity || 120, }, opacity: { value: { min: 0.1, max: 1, }, animation: { count: 0, enable: true, speed: speed || 4, decay: 0, delay: 0, sync: false, mode: "auto", startValue: "random", destroy: "none", }, }, reduceDuplicates: false, shadow: { blur: 0, color: { value: "#000", }, enable: false, offset: { x: 0, y: 0, }, }, shape: { close: true, fill: true, options: {}, type: "circle", }, size: { value: { min: minSize || 1, max: maxSize || 3, }, animation: { count: 0, enable: false, speed: 5, decay: 0, delay: 0, sync: false, mode: "auto", startValue: "random", destroy: "none", }, }, stroke: { width: 0, }, zIndex: { value: 0, opacityRate: 1, sizeRate: 1, velocityRate: 1, }, destroy: { bounds: {}, mode: "none", split: { count: 1, factor: { value: 3, }, rate: { value: { min: 4, max: 9, }, }, sizeOffset: true, }, }, roll: { darken: { enable: false, value: 0, }, enable: false, enlighten: { enable: false, value: 0, }, mode: "vertical", speed: 25, }, tilt: { value: 0, animation: { enable: false, speed: 0, decay: 0, sync: false, }, direction: "clockwise", enable: false, }, twinkle: { lines: { enable: false, frequency: 0.05, opacity: 1, }, particles: { enable: false, frequency: 0.05, opacity: 1, }, }, wobble: { distance: 5, enable: false, speed: { angle: 50, move: 10, }, }, life: { count: 0, delay: { value: 0, sync: false, }, duration: { value: 0, sync: false, }, }, rotate: { value: 0, animation: { enable: false, speed: 0, decay: 0, sync: false, }, direction: "clockwise", path: false, }, orbit: { animation: { count: 0, enable: false, speed: 1, decay: 0, delay: 0, sync: false, }, enable: false, opacity: 1, rotation: { value: 45, }, width: 1, }, links: { blink: false, color: { value: "#fff", }, consent: false, distance: 100, enable: false, frequency: 1, opacity: 1, shadow: { blur: 5, color: { value: "#000", }, enable: false, }, triangles: { enable: false, frequency: 1, }, width: 1, warp: false, }, repulse: { value: 0, enabled: false, distance: 1, duration: 1, factor: 1, speed: 1, }, }, detectRetina: true, }} /> )} </motion.div> );};
Create immersive full-screen experiences perfect for portfolio sites and creative showcases.
Colorful Particles
import React from "react";import { SparklesCore } from '@/components/ui/shadcn-io/sparkles';const Example = () => { return ( <div className="h-[40rem] relative w-full bg-black flex flex-col items-center justify-center overflow-hidden rounded-md"> <div className="w-full absolute inset-0 h-screen"> <SparklesCore id="tsparticlescolorful" background="transparent" minSize={0.6} maxSize={1.4} particleDensity={100} className="w-full h-full" particleColor="#00ff00" speed={0.5} /> </div> <div className="flex flex-col items-center justify-center gap-4 relative z-20"> <h1 className="md:text-7xl text-3xl lg:text-9xl font-bold text-center bg-clip-text text-transparent bg-gradient-to-b from-neutral-50 to-neutral-400"> The Future </h1> <p className="text-neutral-300 cursor-default text-center"> is brighter than you think </p> </div> </div> );};export default Example;
"use client";import React, { useId, useMemo } from "react";import { useEffect, useState } from "react";import Particles, { initParticlesEngine } from "@tsparticles/react";import type { Container, SingleOrMultiple } from "@tsparticles/engine";import { loadSlim } from "@tsparticles/slim";import { cn } from "@/lib/utils";import { motion, useAnimation } from "framer-motion";type ParticlesProps = { id?: string; className?: string; background?: string; particleSize?: number; minSize?: number; maxSize?: number; speed?: number; particleColor?: string; particleDensity?: number;};export const SparklesCore = (props: ParticlesProps) => { const { id, className, background, minSize, maxSize, speed, particleColor, particleDensity, } = props; const [init, setInit] = useState(false); useEffect(() => { initParticlesEngine(async (engine) => { await loadSlim(engine); }).then(() => { setInit(true); }); }, []); const controls = useAnimation(); const particlesLoaded = async (container?: Container) => { if (container) { controls.start({ opacity: 1, transition: { duration: 1, }, }); } }; const generatedId = useId(); return ( <motion.div animate={controls} className={cn("opacity-0", className)}> {init && ( <Particles id={id || generatedId} className={cn("h-full w-full")} particlesLoaded={particlesLoaded} options={{ background: { color: { value: background || "#0d47a1", }, }, fullScreen: { enable: false, zIndex: 1, }, fpsLimit: 120, interactivity: { events: { onClick: { enable: true, mode: "push", }, onHover: { enable: false, mode: "repulse", }, resize: true as any, }, modes: { push: { quantity: 4, }, repulse: { distance: 200, duration: 0.4, }, }, }, particles: { bounce: { horizontal: { value: 1, }, vertical: { value: 1, }, }, collisions: { absorb: { speed: 2, }, bounce: { horizontal: { value: 1, }, vertical: { value: 1, }, }, enable: false, maxSpeed: 50, mode: "bounce", overlap: { enable: true, retries: 0, }, }, color: { value: particleColor || "#ffffff", animation: { h: { count: 0, enable: false, speed: 1, decay: 0, delay: 0, sync: true, offset: 0, }, s: { count: 0, enable: false, speed: 1, decay: 0, delay: 0, sync: true, offset: 0, }, l: { count: 0, enable: false, speed: 1, decay: 0, delay: 0, sync: true, offset: 0, }, }, }, effect: { close: true, fill: true, options: {}, type: {} as SingleOrMultiple<string> | undefined, }, groups: {}, move: { angle: { offset: 0, value: 90, }, attract: { distance: 200, enable: false, rotate: { x: 3000, y: 3000, }, }, center: { x: 50, y: 50, mode: "percent", radius: 0, }, decay: 0, distance: {}, direction: "none", drift: 0, enable: true, gravity: { acceleration: 9.81, enable: false, inverse: false, maxSpeed: 50, }, path: { clamp: true, delay: { value: 0, }, enable: false, options: {}, }, outModes: { default: "out", }, random: false, size: false, speed: { min: 0.1, max: 1, }, spin: { acceleration: 0, enable: false, }, straight: false, trail: { enable: false, length: 10, fill: {}, }, vibrate: false, warp: false, }, number: { density: { enable: true, width: 400, height: 400, }, limit: { mode: "delete", value: 0, }, value: particleDensity || 120, }, opacity: { value: { min: 0.1, max: 1, }, animation: { count: 0, enable: true, speed: speed || 4, decay: 0, delay: 0, sync: false, mode: "auto", startValue: "random", destroy: "none", }, }, reduceDuplicates: false, shadow: { blur: 0, color: { value: "#000", }, enable: false, offset: { x: 0, y: 0, }, }, shape: { close: true, fill: true, options: {}, type: "circle", }, size: { value: { min: minSize || 1, max: maxSize || 3, }, animation: { count: 0, enable: false, speed: 5, decay: 0, delay: 0, sync: false, mode: "auto", startValue: "random", destroy: "none", }, }, stroke: { width: 0, }, zIndex: { value: 0, opacityRate: 1, sizeRate: 1, velocityRate: 1, }, destroy: { bounds: {}, mode: "none", split: { count: 1, factor: { value: 3, }, rate: { value: { min: 4, max: 9, }, }, sizeOffset: true, }, }, roll: { darken: { enable: false, value: 0, }, enable: false, enlighten: { enable: false, value: 0, }, mode: "vertical", speed: 25, }, tilt: { value: 0, animation: { enable: false, speed: 0, decay: 0, sync: false, }, direction: "clockwise", enable: false, }, twinkle: { lines: { enable: false, frequency: 0.05, opacity: 1, }, particles: { enable: false, frequency: 0.05, opacity: 1, }, }, wobble: { distance: 5, enable: false, speed: { angle: 50, move: 10, }, }, life: { count: 0, delay: { value: 0, sync: false, }, duration: { value: 0, sync: false, }, }, rotate: { value: 0, animation: { enable: false, speed: 0, decay: 0, sync: false, }, direction: "clockwise", path: false, }, orbit: { animation: { count: 0, enable: false, speed: 1, decay: 0, delay: 0, sync: false, }, enable: false, opacity: 1, rotation: { value: 45, }, width: 1, }, links: { blink: false, color: { value: "#fff", }, consent: false, distance: 100, enable: false, frequency: 1, opacity: 1, shadow: { blur: 5, color: { value: "#000", }, enable: false, }, triangles: { enable: false, frequency: 1, }, width: 1, warp: false, }, repulse: { value: 0, enabled: false, distance: 1, duration: 1, factor: 1, speed: 1, }, }, detectRetina: true, }} /> )} </motion.div> );};
Brand-matched particle effects that harmonize with your existing design language and color palette.
Use Cases
This free open source React component works well for:
- Creative portfolios - Artistic backgrounds showcasing innovation without overwhelming content built with Next.js
- Product launches - Interactive celebration effects generating excitement during key moments using TypeScript
- Gaming interfaces - Magical atmosphere for dashboards and character selection screens
- Event websites - Dynamic particle systems creating anticipation with user engagement using shadcn/ui design
- Interactive showcases - Demonstrating technical skill with smooth, performant animations
- Brand experiences - Expressing personality through customizable colors and interaction patterns using Tailwind CSS
API Reference
SparklesCore
Prop | Type | Default | Description |
---|---|---|---|
id | string | auto-generated | Unique identifier for the particles instance |
className | string | - | Additional CSS classes for the container |
background | string | "#0d47a1" | Background color of the particles container |
minSize | number | 1 | Minimum size of particles |
maxSize | number | 3 | Maximum size of particles |
speed | number | 4 | Animation speed of particle opacity changes |
particleColor | string | "#ffffff" | Color of the particles (hex, rgb, hsl) |
particleDensity | number | 120 | Number of particles to render |
Implementation Notes
- Component uses tsParticles engine with hardware acceleration for optimal performance
- Click interactions spawn four particles per click with realistic physics and collision dynamics
- Particle density configurable from 50 (subtle) to 300+ (celebration) for different use cases
- Color customization supports hex (#ff6b6b), RGB (rgb(107, 203, 255)), and HSL (hsl(290, 100%, 71%)) formats
- Mobile optimization automatically reduces particle count for smooth 60fps on all devices
- Background transparency supported via
background="transparent"
for overlay effects - Framer Motion integration provides smooth fade-in animations respecting user motion preferences
- Memory management includes automatic cleanup preventing performance degradation over time
- Compatible with shadcn/ui design system and Tailwind CSS utility classes
Shooting Stars
Animated meteor shower effects with customizable colors and trajectories. Perfect for React applications requiring dynamic sky animations with Next.js integration and TypeScript support.
Spiral Animation
Mesmerizing spiral animations with GSAP-powered smooth motion. Perfect for React applications requiring hypnotic visual effects with Next.js integration and TypeScript support.