Particles
The Particles component creates a subtle animated background effect with floating particles. It’s perfect for adding visual interest to hero sections, landing pages, or any area that needs a dynamic atmosphere.
Usage
<script>
import Particles from "$lib/components/ui/particles/particles.svelte";
</script>
<Particles />
Examples
Basic Particles
The default particles background effect.
Particles Background
With Content Overlay
Particles as a background with content positioned on top.
magic.mov
A collection of experimental filmmaking tools to enhance your creative process
API Reference
The Particles component doesn’t accept any props as it’s designed to be a full-screen background element.
Implementation
The Particles component uses the HTML Canvas API to create and animate floating particles. It handles initialization, animation, and cleanup automatically:
<script lang="ts">
import { onMount } from 'svelte';
interface Particle {
x: number;
y: number;
vx: number;
vy: number;
size: number;
alpha: number;
}
let canvas: HTMLCanvasElement;
let ctx: CanvasRenderingContext2D;
let particles: Particle[] = [];
let animationFrame: number;
let width: number;
let height: number;
const PARTICLE_COUNT = 50;
const PARTICLE_SIZE_RANGE = { min: 2, max: 4 };
const SPEED_RANGE = { min: -0.5, max: 0.5 };
function createParticle(): Particle {
return {
x: Math.random() * width,
y: Math.random() * height,
vx: SPEED_RANGE.min + Math.random() * (SPEED_RANGE.max - SPEED_RANGE.min),
vy: SPEED_RANGE.min + Math.random() * (SPEED_RANGE.max - SPEED_RANGE.min),
size:
PARTICLE_SIZE_RANGE.min +
Math.random() * (PARTICLE_SIZE_RANGE.max - PARTICLE_SIZE_RANGE.min),
alpha: 0.1 + Math.random() * 0.4
};
}
function initParticles() {
particles = Array(PARTICLE_COUNT).fill(null).map(createParticle);
}
function updateParticles() {
particles.forEach((p) => {
p.x += p.vx;
p.y += p.vy;
if (p.x < 0) p.x = width;
if (p.x > width) p.x = 0;
if (p.y < 0) p.y = height;
if (p.y > height) p.y = 0;
});
}
function draw() {
ctx.clearRect(0, 0, width, height);
particles.forEach((p) => {
ctx.beginPath();
ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
ctx.fillStyle = `rgba(255, 255, 255, ${p.alpha})`;
ctx.fill();
});
updateParticles();
animationFrame = requestAnimationFrame(draw);
}
function handleResize() {
width = window.innerWidth;
height = window.innerHeight;
canvas.width = width;
canvas.height = height;
initParticles();
}
onMount(() => {
ctx = canvas.getContext('2d')!;
handleResize();
window.addEventListener('resize', handleResize);
draw();
return () => {
window.removeEventListener('resize', handleResize);
cancelAnimationFrame(animationFrame);
};
});
</script>
<canvas bind:this={canvas} class="pointer-events-none fixed inset-0 -z-10"></canvas>
The component automatically:
- Initializes particles when mounted
- Handles window resizing
- Animates particles with subtle movements
- Properly cleans up when unmounted to prevent memory leaks
Note that the particles are rendered with a negative z-index (-z-10
) to ensure they appear behind other content.