Overview
Canvas Confetti is a lightweight JavaScript library for creating customizable confetti animations
using the HTML canvas. It's perfect for celebrations, achievements, and delightful UI touches.
You can include this library in your project using a CDN link.
<script src="https://cdn.jsdelivr.net/npm/canvas-confetti@1.9.3/dist/confetti.browser.min.js"></script>
Each example below demonstrates a different style and use of confetti, from basic bursts to continuous
effects like snow or fireworks.
Basic Example
This is a simple confetti burst. When the button is clicked, a group of particles is launched from the
center-bottom of the screen. It uses the default colors and settings with a moderate spread.
<button class="btn btn-primary" id="basicConfetti">Run<i class="ri-play-fill ms-2"></i></button>
<button class="btn btn-primary" id="basicConfetti">Run<i
class="ri-play-fill ms-2"></i></button>
document.getElementById('basicConfetti').addEventListener('click', function () {
confetti({
particleCount: 100,
spread: 75,
origin: { y: 0.6 }
});
});
document.getElementById('basicConfetti').addEventListener('click', function () {
confetti({ particleCount: 100, spread: 75, origin: { y: 0.6 } }); });
Random Direction Example
This variation launches confetti in a random direction each time it's triggered. It introduces
randomness in the angle, spread, and particle count to create an unpredictable but visually fun
experience.
<button class="btn btn-primary" id="randomConfetti">Run<i class="ri-play-fill ms-2"></i></button>
<button class="btn btn-primary" id="randomConfetti">Run<i
class="ri-play-fill ms-2"></i></button>
document.getElementById('randomConfetti').addEventListener('click', function () {
function randomInRange(min, max) {
return Math.random() * (max - min) + min;
}
confetti({
angle: randomInRange(50, 130),
spread: randomInRange(50, 70),
particleCount: randomInRange(50, 100),
origin: { y: 0.6 }
});
});
document.getElementById('randomConfetti').addEventListener('click', function ()
{ function randomInRange(min, max) { return Math.random() * (max - min) + min; } confetti({
angle: randomInRange(50, 130), spread: randomInRange(50, 70), particleCount: randomInRange(50,
100), origin: { y: 0.6 } }); });
Realistic Example
This example mimics a more natural confetti burst by firing several small bursts in quick succession,
each with slightly different settings. It simulates the way real confetti behaves when launched from a
cannon.
<button class="btn btn-primary" id="realisticConfetti">Run<i class="ri-play-fill ms-2"></i></button>
<button class="btn btn-primary" id="realisticConfetti">Run<i
class="ri-play-fill ms-2"></i></button>
document.getElementById('realisticConfetti').addEventListener('click', function () {
var count = 200;
var defaults = {
origin: { y: 0.6 }
};
function fire(particleRatio, opts) {
confetti({
...defaults,
...opts,
particleCount: Math.floor(count * particleRatio)
});
}
fire(0.25, {
spread: 30,
startVelocity: 50,
});
fire(0.2, {
spread: 60,
});
fire(0.35, {
spread: 100,
decay: 0.9,
scalar: 0.8
});
fire(0.1, {
spread: 120,
startVelocity: 25,
decay: 0.9,
scalar: 1.2
});
fire(0.1, {
spread: 120,
startVelocity: 40,
});
});
document.getElementById('realisticConfetti').addEventListener('click', function
() { var count = 200; var defaults = { origin: { y: 0.6 } }; function fire(particleRatio, opts)
{ confetti({ ...defaults, ...opts, particleCount: Math.floor(count * particleRatio) }); }
fire(0.25, { spread: 30, startVelocity: 50, }); fire(0.2, { spread: 60, }); fire(0.35, { spread:
100, decay: 0.9, scalar: 0.8 }); fire(0.1, { spread: 120, startVelocity: 25, decay: 0.9, scalar:
1.2 }); fire(0.1, { spread: 120, startVelocity: 40, }); });
Fireworks Example
Simulates a fireworks show by launching confetti from multiple random positions on the screen over a
fixed duration. It mimics the way fireworks explode across the sky at random intervals and locations.
<button class="btn btn-primary" id="fireworksConfetti">Run<i class="ri-play-fill ms-2"></i></button>
<button class="btn btn-primary" id="fireworksConfetti">Run<i
class="ri-play-fill ms-2"></i></button>
document.getElementById('fireworksConfetti').addEventListener('click', function () {
var duration = 15 * 1000;
var animationEnd = Date.now() + duration;
var defaults = { startVelocity: 30, spread: 360, ticks: 60, zIndex: 0 };
function randomInRange(min, max) {
return Math.random() * (max - min) + min;
}
var interval = setInterval(function() {
var timeLeft = animationEnd - Date.now();
if (timeLeft <= 0) {
return clearInterval(interval);
}
var particleCount = 50 * (timeLeft / duration);
// since particles fall down, start a bit higher than random
confetti({ ...defaults, particleCount, origin: { x: randomInRange(0.1, 0.3), y: Math.random() - 0.2 } });
confetti({ ...defaults, particleCount, origin: { x: randomInRange(0.7, 0.9), y: Math.random() - 0.2 } });
}, 250);
});
document.getElementById('fireworksConfetti').addEventListener('click', function
() { var duration = 15 * 1000; var animationEnd = Date.now() + duration; var defaults = {
startVelocity: 30, spread: 360, ticks: 60, zIndex: 0 }; function randomInRange(min, max) {
return Math.random() * (max - min) + min; } var interval = setInterval(function() { var timeLeft
= animationEnd - Date.now(); if (timeLeft <= 0) { return clearInterval(interval); } var
particleCount = 50 * (timeLeft / duration); // since particles fall down, start a bit higher
than random confetti({ ...defaults, particleCount, origin: { x: randomInRange(0.1, 0.3), y:
Math.random() - 0.2 } }); confetti({ ...defaults, particleCount, origin: { x: randomInRange(0.7,
0.9), y: Math.random() - 0.2 } }); }, 250); });
Stars Example
This example mixes star-shaped and circle-shaped particles for a celebratory sparkle effect. Particles
are launched in short bursts with bright, festive colors and no gravity, causing them to float around
like twinkling stars.
<button class="btn btn-primary" id="starsConfetti">Run<i class="ri-play-fill ms-2"></i></button>
<button class="btn btn-primary" id="starsConfetti">Run<i
class="ri-play-fill ms-2"></i></button>
document.getElementById('starsConfetti').addEventListener('click', function () {
var defaults = {
spread: 360,
ticks: 50,
gravity: 0,
decay: 0.95,
startVelocity: 30,
colors: ['FFE400', 'FFBD00', 'E89400', 'FFCA6C', 'FDFFB8']
};
function shoot() {
confetti({
...defaults,
particleCount: 40,
scalar: 1.2,
shapes: ['star']
});
confetti({
...defaults,
particleCount: 10,
scalar: 0.75,
shapes: ['circle']
});
}
setTimeout(shoot, 0);
setTimeout(shoot, 100);
setTimeout(shoot, 200);
});
document.getElementById('starsConfetti').addEventListener('click', function () {
var defaults = { spread: 360, ticks: 50, gravity: 0, decay: 0.95, startVelocity: 30, colors:
['FFE400', 'FFBD00', 'E89400', 'FFCA6C', 'FDFFB8'] };
function shoot() { confetti({ ...defaults, particleCount: 40, scalar: 1.2, shapes:
['star'] }); confetti({ ...defaults, particleCount: 10, scalar: 0.75, shapes:
['circle'] }); } setTimeout(shoot, 0); setTimeout(shoot, 100); setTimeout(shoot, 200);
});
Snow Example
This creates a continuous snowfall effect by launching individual white confetti circles that drift
down the screen. It uses a recursive requestAnimationFrame loop to simulate snow falling
over time.
<button class="btn btn-primary" id="snowConfetti">Run<i class="ri-play-fill ms-2"></i></button>
<button class="btn btn-primary" id="snowConfetti">Run<i
class="ri-play-fill ms-2"></i></button>
document.getElementById('snowConfetti').addEventListener('click', function () {
var duration = 15 * 1000;
var animationEnd = Date.now() + duration;
var skew = 1;
function randomInRange(min, max) {
return Math.random() * (max - min) + min;
}
(function frame() {
var timeLeft = animationEnd - Date.now();
var ticks = Math.max(200, 500 * (timeLeft / duration));
skew = Math.max(0.8, skew - 0.001);
confetti({
particleCount: 1,
startVelocity: 0,
ticks: ticks,
origin: {
x: Math.random(),
// since particles fall down, skew start toward the top
y: (Math.random() * skew) - 0.2
},
colors: ['#daecff'],
shapes: ['circle'],
gravity: randomInRange(0.4, 0.6),
scalar: randomInRange(0.4, 1),
drift: randomInRange(-0.4, 0.4)
});
if (timeLeft > 0) {
requestAnimationFrame(frame);
}
}());
});
document.getElementById('snowConfetti').addEventListener('click', function () {
var duration = 15 * 1000; var animationEnd = Date.now() + duration; var skew = 1; function
randomInRange(min, max) { return Math.random() * (max - min) + min; } (function frame() { var
timeLeft = animationEnd - Date.now(); var ticks = Math.max(200, 500 * (timeLeft / duration));
skew = Math.max(0.8, skew - 0.001); confetti({ particleCount: 1, startVelocity: 0, ticks: ticks,
origin: { x: Math.random(), // since particles fall down, skew start toward the top y:
(Math.random() * skew) - 0.2 }, colors: ['#daecff'], shapes: ['circle'],
gravity: randomInRange(0.4, 0.6), scalar: randomInRange(0.4, 1), drift: randomInRange(-0.4, 0.4)
}); if (timeLeft > 0) { requestAnimationFrame(frame); } }()); });
School Pride Example
This example shows how to fire confetti from both sides of the screen using your school or team
colors. It continuously emits confetti particles from left and right angles, creating a "pride
tunnel" effect. You can customize the colors array for your own branding.
<button class="btn btn-primary" id="schoolPrideConfetti">Run<i class="ri-play-fill ms-2"></i></button>
<button class="btn btn-primary" id="schoolPrideConfetti">Run<i
class="ri-play-fill ms-2"></i></button>
document.getElementById('schoolPrideConfetti').addEventListener('click', function () {
var end = Date.now() + (15 * 1000);
// go Buckeyes!
var colors = ['#bb0000', '#e64343'];
(function frame() {
confetti({
particleCount: 2,
angle: 60,
spread: 55,
origin: { x: 0 },
colors: colors
});
confetti({
particleCount: 2,
angle: 120,
spread: 55,
origin: { x: 1 },
colors: colors
});
if (Date.now() < end) {
requestAnimationFrame(frame);
}
}());
});
document.getElementById('schoolPrideConfetti').addEventListener('click',
function () { var end = Date.now() + (15 * 1000); // go Buckeyes! var colors =
['#bb0000', '#e64343']; (function frame() { confetti({ particleCount: 2, angle:
60, spread: 55, origin: { x: 0 }, colors: colors }); confetti({ particleCount: 2, angle: 120,
spread: 55, origin: { x: 1 }, colors: colors }); if (Date.now() < end) {
requestAnimationFrame(frame); } }()); });