✨ Cursor FX
Beautiful, customizable cursor particle effects for React and vanilla JavaScript. Create magical experiences with effects like bubbles, snow, sparkles, and more!

🎮 Live Demo | 📖 Documentation | ⭐ GitHub

✨ Experience magical cursor effects with 6 stunning built-in animations ✨
✨ Features
- 🎨 6 Built-in Effects: Bubbles, Snow, Fairy Dust, Sparkle, Confetti, Retro CRT
- ⚡ High Performance: Optimized canvas rendering with smart throttling
- 🎯 TypeScript Support: Full type definitions included
- 📦 Tiny Bundle: Lightweight with minimal dependencies
- 🎭 Customizable: Colors, size, speed, and behavior all configurable
- ⚛️ React Ready: Dedicated React components with hooks
- 🌐 Vanilla JS: Works with any framework or no framework
- 🖼️ Image Support: Use PNG assets for realistic effects
📦 Installation
npm install cursor-fx
yarn add cursor-fx
pnpm add cursor-fx
🚀 Quick Start
React
import { CursorFX } from 'cursor-fx/react';
function App() {
return (
<>
<CursorFX effect="bubble" />
<YourContent />
</>
);
}
Vanilla JavaScript
import { initCursorFX } from 'cursor-fx/vanilla';
const fx = initCursorFX({
effect: 'snow',
particleCount: 2
});
fx.destroy();
CDN (No Build Step)
Use directly in your HTML without any build tools:
<!DOCTYPE html>
<html>
<head>
<title>My Website</title>
</head>
<body>
<h1>Hello World</h1>
<script src="https://unpkg.com/cursor-fx@latest/dist/cdn/cursor-fx.min.js"></script>
<script>
const fx = CursorFX.initCursorFX({
effect: 'bubble'
});
</script>
</body>
</html>
CDN Options:
- unpkg:
https://unpkg.com/cursor-fx@latest/dist/cdn/cursor-fx.min.js
- jsdelivr:
https://cdn.jsdelivr.net/npm/cursor-fx@latest/dist/cdn/cursor-fx.min.js
Available via global CursorFX object:
CursorFX.initCursorFX(options) - Initialize effects
CursorFX.ImageLoader - Preload images (optional)
🎨 Available Effects
🫧 Bubble
Floating soap bubbles that drift upward with a smooth pop-up animation.
<CursorFX effect="bubble" />
Features:
- Transparent, realistic bubble rendering
- Gentle upward float with wobble physics
- Smooth scale-up animation on spawn (pops from 30% to 100% size)
- Variable bubble sizes (37-112px)
❄️ Snow
Delicate snowflakes that fall and drift with wind.
<CursorFX effect="snow" />
Features:
- Rotating snowflakes with 6-armed crystalline structure
- Wind drift using smooth sine wave physics
- White glow for visibility
- Dual mode: PNG images or optimized canvas drawing
✨ Fairy Dust
Golden magical particles that float upward.
<CursorFX effect="fairyDust" />
Features:
- Golden glow effect (shadowBlur: 18px)
- Cross/plus shape particles
- Upward floating motion (negative gravity)
- Perfect for magical themes
⭐ Sparkle
Quick, colorful sparkles that burst and fade.
<CursorFX effect="sparkle" />
Features:
- Rainbow colored particles
- Fast, energetic movement
- Short lifetime (20 frames) for clean trails
- Star-shaped particles
🎉 Confetti
Celebratory confetti that falls from cursor.
<CursorFX effect="confetti" />
Features:
- Party color palette
- Rectangle particles with rotation
- Realistic falling physics
- Perfect for celebrations
🖥️ Retro CRT
Phosphor green glow like old computer terminals.
<CursorFX effect="retroCRT" />
Features:
- Classic phosphor green colors
- Circular particles with strong glow
- Stationary particles (zero gravity)
- Nostalgic terminal aesthetic
⚙️ Configuration
All effects support extensive customization:
<CursorFX
effect="bubble"
particleCount={3}
colors={['#FF6B6B', '#4ECDC4', '#FFE66D']}
/>
Common Options
effect | CursorEffectType | Effect name | Required |
particleCount | number | Particles per spawn | Effect-specific |
colors | string[] | Particle colors | Effect-specific |
particleSize | number | Base particle size | Effect-specific |
enabled | boolean | Enable/disable | true (React) |
Advanced Options
interface EffectOptions {
colors?: string[];
particleCount?: number;
particleSize?: number;
gravity?: number;
maxLife?: number;
velocity?: number;
throttle?: number;
minMoveDistance?: number;
}
Effect-Specific Defaults
See EFFECT_DEFAULTS.md for complete default values.
Quick Reference:
<CursorFX effect="bubble" />
<CursorFX effect="snow" />
<CursorFX effect="bubble" particleCount={5} />
<CursorFX effect="snow" colors={['#FFFFFF']} />
📚 API Reference
React Component
import { CursorFX } from 'cursor-fx/react';
<CursorFX
enabled={true}
effect="bubble"
particleCount={2}
colors={['#FFD700', '#FF69B4']}
/>
Props:
enabled?: boolean - Enable/disable effect
effect: CursorEffectType - Effect name
- All
EffectOptions are also valid props
Vanilla JS
import { initCursorFX } from 'cursor-fx/vanilla';
const fx = initCursorFX({
effect: 'snow',
particleCount: 3,
colors: ['#FFFFFF', '#E0FFFF']
});
fx.destroy();
Core Engine (Advanced)
For advanced use cases, use the core engine directly:
import {
CursorFXEngine,
createBubbleEffect,
ImageLoader
} from 'cursor-fx';
await ImageLoader.loadBubbles('/bubbles');
await ImageLoader.loadSnowflakes('/snowflakes');
const engine = new CursorFXEngine();
const effect = createBubbleEffect({
particleCount: 2,
colors: ['#ADD8E6']
});
engine.start(effect);
engine.stop();
engine.destroy();
🖼️ Using Image Assets
The Bubble and Snow effects support PNG images for photorealistic quality. If images aren't loaded, they automatically fall back to canvas-drawn shapes.
Setting Up Image Assets
1. Copy the images to your public directory:
The package includes high-quality PNG assets. Copy them from node_modules/cursor-fx/dist/bubbles/ and node_modules/cursor-fx/dist/snowflakes/ to your project's public directory:
public/
bubbles/
soap_bubbles_1.png
soap_bubble_2.png
soap_bubble_3.png
snowflakes/
snow_flake_1.png
snow_flake_2.png
2. Preload images before using the effects:
React Example
import { useEffect } from 'react';
import { CursorFX, ImageLoader } from 'cursor-fx/react';
function App() {
useEffect(() => {
ImageLoader.loadBubbles('/bubbles')
.then(() => console.log('✓ Bubble images loaded'))
.catch(err => console.warn('Failed to load bubbles:', err));
ImageLoader.loadSnowflakes('/snowflakes')
.then(() => console.log('✓ Snowflake images loaded'))
.catch(err => console.warn('Failed to load snowflakes:', err));
}, []);
return <CursorFX effect="bubble" />;
}
Vanilla JavaScript Example
import { initCursorFX, ImageLoader } from 'cursor-fx/vanilla';
Promise.all([
ImageLoader.loadBubbles('/bubbles'),
ImageLoader.loadSnowflakes('/snowflakes')
])
.then(() => {
console.log('✓ All images loaded');
const fx = initCursorFX({ effect: 'bubble' });
})
.catch(err => {
console.warn('Failed to load images:', err);
const fx = initCursorFX({ effect: 'bubble' });
});
CDN Example
<script src="https://unpkg.com/cursor-fx@latest/dist/cdn/cursor-fx.min.js"></script>
<script>
CursorFX.ImageLoader.loadBubbles('/bubbles')
.then(() => {
const fx = CursorFX.initCursorFX({ effect: 'bubble' });
});
</script>
ImageLoader API
ImageLoader.loadBubbles(basePath?: string): Promise<HTMLImageElement[]>
ImageLoader.loadSnowflakes(basePath?: string): Promise<HTMLImageElement[]>
ImageLoader.loadImage(src: string): Promise<HTMLImageElement>
ImageLoader.isLoaded(): boolean
ImageLoader.clear(): void
Required file names:
- Bubbles:
soap_bubbles_1.png, soap_bubble_2.png, soap_bubble_3.png
- Snowflakes:
snow_flake_1.png, snow_flake_2.png
Fallback Behavior:
If images fail to load or aren't preloaded, bubble and snow effects automatically use optimized canvas rendering instead. Your effects will always work!
Included Assets:
- 3 bubble variations (~148KB total)
- 2 snowflake variations (~140KB total)
Assets are bundled at dist/bubbles/ and dist/snowflakes/.
🎨 Customizing Colors
Each effect has themed default colors, but you can easily customize:
<CursorFX
effect="bubble"
colors={[
'rgba(255, 192, 203, 0.4)',
'rgba(255, 182, 193, 0.4)',
]}
/>
<CursorFX
effect="snow"
colors={['#E0FFFF', '#F0F8FF', '#F5FFFA']}
/>
<CursorFX
effect="sparkle"
colors={['#FF0000', '#00FF00', '#0000FF']}
/>
📱 Performance Tips
- Reduce Spawn Rate: Increase
throttle and minMoveDistance
<CursorFX
effect="bubble"
throttle={200}
minMoveDistance={20}
/>
- Lower Particle Count: Reduce particles per spawn
<CursorFX effect="snow" particleCount={1} />
- Shorter Lifetime: Particles disappear faster
<CursorFX effect="sparkle" maxLife={15} />
- Disable on Mobile: Conditional rendering
const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
<CursorFX effect="bubble" enabled={!isMobile} />
🔧 Advanced Usage
Multiple Effects with Switching
function App() {
const [effect, setEffect] = useState('bubble');
return (
<>
<CursorFX effect={effect} />
<button onClick={() => setEffect('snow')}>Snow</button>
<button onClick={() => setEffect('bubble')}>Bubble</button>
<button onClick={() => setEffect('confetti')}>Confetti</button>
</>
);
}
Dynamic Configuration
const [config, setConfig] = useState({
particleCount: 2,
colors: ['#FFD700', '#FFC700']
});
<CursorFX effect="fairyDust" {...config} />
<button onClick={() => setConfig({...config, particleCount: 5})}>
More Particles
</button>
Conditional Effects
<CursorFX
effect="confetti"
enabled={isCelebrating}
particleCount={8}
/>
🌐 Browser Compatibility
Works in all modern browsers that support:
- Canvas API
- ES2020+
- RequestAnimationFrame
Mobile Support: Touch events fully supported.
Performance Optimizations:
- Max 500 particles to prevent lag
- Smart throttling (~60fps)
- Wind drift with smooth Perlin-like noise
- Optimized canvas rendering (single-path snowflakes = 18x faster)
📦 Bundle Size
Optimized for minimal impact:
- Core: ~6KB (minified + gzipped)
- React: ~7KB (minified + gzipped)
- Vanilla: ~6KB (minified + gzipped)
Dependencies:
- Zero runtime dependencies
- React is a peer dependency (optional)
🎯 TypeScript
Full TypeScript support included:
import type { CursorEffectType, EffectOptions } from 'cursor-fx';
import type { CursorFXProps } from 'cursor-fx/react';
const effect: CursorEffectType = 'bubble';
const options: EffectOptions = {
particleCount: 3,
colors: ['#FF0000']
};
📂 Examples
Working examples included:
examples/react/ - Vite + React demo
examples/vanilla/ - Plain HTML demo
Run examples:
cd examples/react
npm install
npm run dev
🤝 Contributing
Contributions welcome! Please feel free to submit a Pull Request.
📄 License
MIT © [Your Name]
🙏 Acknowledgments
Built with:
- TypeScript
- React (peer dependency)
- HTML5 Canvas API
- tsup for bundling
🔗 Links
Made with ✨ by Anto Pravin C