Svelte Confetti

Add a little bit of flair to your app with some confetti 🎊! There are no dependencies and it's tiny in size. Even better; it works without JavaScript with the help of SSR in SvelteKit (this page doesn't use SSR though)!

GitHub | REPL

Demo

Click these buttons to see their effect. Most of these are not just a single toggle, they are a combination of multiple props. Don't worry we'll go over each one in the documentation further down the page!


Click in me

Installation

Install using Yarn or NPM.

yarn add svelte-confetti --dev npm install svelte-confetti --save-dev

Include the component in your app.

import { Confetti } from "svelte-confetti" <Confetti />

Usage

The Confetti comes without the buttons you will see in these examples. The buttons are simply used to demonstrate the effect in these docs.
The component in it's most basic form.
<Confetti />

Spread

The spread of confetti can be adjusted. The props x and y are used to determine how far the confetti spreads. For both values multipliers are used and these are to be supplied in an array of two with the lowest number first. For each confetti piece a random number between these two is picked. The higher the number the futher the spread. Negative numbers affect the direction.
<Confetti x={[-0.5, 0.5]} y={[0.25, 1]} />
<Confetti x={[-1, -0.25]} y={[0, 0.5]} />
<Confetti x={[0.25, 1]} y={[0, 0.5]} />
<Confetti x={[-0.25, 0.25]} y={[0.75, 1.5]} />
<Confetti x={[-0.25, 0.25]} y={[-0.75, -0.25]} />
<Confetti x={[-0.5, 0.5]} y={[-0.5, -0.5]} />

Amount

The amount of particles that are launched can be adjusted with the amount property. This should always be a whole number. Be careful with going too high as it may impact performance. It will depends on the device and other performance heavy elements on the page, but try and keep it below 500.
<Confetti amount=10 />
<Confetti amount=50 />
<Confetti amount=200 />
<Confetti amount=500 />

Shape

As you may have noticed from the previous buttons, the confetti tends to take on a fairly square shape. This can be mitigated a little bit by using the propery cone. This will cause the confetti to launch in a more cone like shape which is especially nice when using lots of particles.
<Confetti amount=200 />
<Confetti cone amount=200 />
This is especially effective when firing to the side, but we need to compensate with a larger x multiplier.
<Confetti x={[0.25, 1]} y={[0, 0.5]} />
<Confetti cone x={[1, 2.5]} y={[0.25, 0.75]} />
The cones still have a fairly distinct cone shape to them, later on in these docs we will go over how to mitigate this.

Size

The size of the confetti pieces can be adjusted using the size property.
<Confetti size=2 />
<Confetti size=30 />
We can also adjust the shape of the confetti pieces using the rounded property
<Confetti rounded size=30 />

Timing

By default all confetti comes out at just about the same time. There is a little bit of variance but it appears instant. That's what a confetti cannon does. We can change when each piece is fired by adjusted the range of the delay property. The delay is given in milliseconds.
<Confetti delay={[0, 250]} />
<Confetti delay={[0, 1500]} />
We can also opt to have the animation play infinitely by setting the infinite property, at this point the delay mostly has a effect only when spawning in for the first time. (Click the button again to toggle it off)
<Confetti infinite />
<Confetti infinite delay={[0, 1500]} />
Alternatively we can let the animation play out fully before repeating. For this we can use the iterationCount property. This is especially useful during development to tweak the confetti without having to reload the page or set up a button. This can be set to a number or to "infinite", basically anything that would be accepted by the animation-iteration-count property in CSS.
<Confetti iterationCount=infinite />

Color

You can adjust the colors of the confetti pieces in different ways. You can specify a hue using the colorRange property, which will use HSL colors with 75% saturation and 50% lightness. 0-360 is all colors, 75-175 would be only greens. Alternatively you can specifiy colors in an array using colorArray. This can take any CSS value that would be accepted as the background property. RGB, HEX, HSL, but even gradients and images.
<Confetti colorRange={[75, 175]} />
<Confetti colorArray={["#ffbe0b", "#fb5607", "#ff006e", "#8338ec", "#3a86ff"]} />
<Confetti colorArray={["var(--primary)", "rgba(0, 255, 0, 0.5)", "white"]} />
It's not just colors though, we can input any value valid to the background css property. This includes gradients and images.
<Confetti colorArray={["linear-gradient(var(--primary), blue)"]} />
<Confetti colorArray={["url(https://svelte.dev/favicon.png)", "url(https://github.githubassets.com/favicons/favicon-dark.png)"]} />
Or we could set up a random color each time the component is mounted.
<Confetti colorArray={[`hsl(${Math.floor(Math.random() * 360)}, 75%, 50%)`]} />

Gravity

We can change how the confetti falls using the fallDistance property. We can make it fall faster, slow, or stop it from falling altogether. This property will accept any valid css property, except for 0.
<Confetti fallDistance=50px />
<Confetti fallDistance=200px />
Notice how it's set to 0px and not just 0
<Confetti fallDistance=0px />
We can also disable gravity and air resistance altogether and make it travel at a constant speed by setting the noGravity property.
<Confetti noGravity duration=500 />
<Confetti noGravity duration=500 x={[-0.5, 0.5]} y={[-0.5, 0.5]} />
We can set how far the particles spread horizontally before and after the peak using the xSpread property. This expects a number between 0 and 1 but you can set it higher or lower for some odd results.
<Confetti xSpread=0.1 />
<Confetti xSpread=0.4 />

Multiple components

We can combine multiple Confetti components to create neat effects.
For example we could combine multiple components each with different colors and different areas to create flags! (Blues aren't the actual flag colors to make it a little easier to see on dark backgrounds)

<Confetti y={[1.25, 1.5]} x={[-1, 1]} colorArray={["#c8102e"]} />
<Confetti y={[1, 1.25]} x={[-1, 1]} colorArray={["white"]} />
<Confetti y={[0.75, 1]} x={[-1, 1]} colorArray={["#3350ec"]} />

<Confetti y={[0.75, 1.5]} x={[-1, 1]} colorArray={["#004b87"]} amount=100 />
<Confetti y={[1.05, 1.20]} x={[-1, 1]} colorArray={["#ffcd00"]} amount=50 />
<Confetti y={[0.75, 1.5]} x={[-0.5, -0.25]} colorArray={["#ffcd00"]} amount=20 />

This one is heavy! This uses 1015 effects, more than recommended, but it looks neat! <Confetti y={[1.20, 1.45]} x={[-0.95, -0.3]} colorArray={["white"]} size=5 />
<Confetti y={[1.45, 1.5]} x={[-0.25, 1]} colorArray={["#bf0d3e"]} amount=70 />
<Confetti y={[1.4, 1.45]} x={[-0.25, 1]} colorArray={["white"]} amount=70 />
<Confetti y={[1.35, 1.4]} x={[-0.25, 1]} colorArray={["#bf0d3e"]} amount=70 />
<Confetti y={[1.3, 1.35]} x={[-0.25, 1]} colorArray={["white"]} amount=70 />
<Confetti y={[1.25, 1.3]} x={[-0.25, 1]} colorArray={["#bf0d3e"]} amount=70 />
<Confetti y={[1.2, 1.25]} x={[-0.25, 1]} colorArray={["white"]} amount=70 />
<Confetti y={[1.15, 1.2]} x={[-0.25, 1]} colorArray={["#bf0d3e"]} amount=70 />
<Confetti y={[1.1, 1.15]} x={[-1, 1]} colorArray={["white"]} amount=70 />
<Confetti y={[1.05, 1.1]} x={[-1, 1]} colorArray={["#bf0d3e"]} amount=70 />
<Confetti y={[1, 1.05]} x={[-1, 1]} colorArray={["white"]} amount=70 />
<Confetti y={[0.95, 1]} x={[-1, 1]} colorArray={["#bf0d3e"]} amount=70 />
<Confetti y={[0.9, 0.95]} x={[-1, 1]} colorArray={["white"]} amount=70 />
<Confetti y={[0.85, 0.9]} x={[-1, 1]} colorArray={["#bf0d3e"]} amount=70 />

Flags are cool, but we can do plenty of other things. In this example we will "feather" the initial effect to give it a less defined shape. By default the effects have a fairly distinct shape to them which ruins the effect a little bit, especially when using lots of particles.
<Confetti y={[1.25, 1.5]} x={[-1, 1]} colorArray={["#c8102e"]} />
<Confetti x={[-0.5, 0.5]} /> <Confetti amount=10 x={[-0.75, -0.3]} y={[0.15, 0.75]} /> <Confetti amount=10 x={[0.3, 0.75]} y={[0.15, 0.75]} />
And with the cone property
<Confetti cone amount=70 x={[-0.5, 0.5]} />
<Confetti cone x={[-0.5, 0.5]} /> <Confetti cone amount=10 x={[-0.75, -0.4]} y={[0.15, 0.75]} /> <Confetti cone amount=10 x={[0.4, 0.75]} y={[0.15, 0.75]} />
We can also combine this with a large delay to mitigate the effect further, but it makes it less cannon-y.
<Confetti x={[-0.5, 0.5]} delay={[0, 250]} /> <Confetti amount=10 x={[-0.75, -0.3]} y={[0.15, 0.75]} delay={[0, 1000]} /> <Confetti amount=10 x={[0.3, 0.75]} y={[0.15, 0.75]} delay={[0, 1000]} />
We could also combine multiple components to create animations.
<Confetti cone x={[-1, -0.25]} colorRange={[100, 200]} /> <Confetti cone x={[-0.35, 0.35]} delay={[500, 550]} colorRange={[200, 300]} /> <Confetti cone x={[0.25, 1]} delay={[250, 300]} colorRange={[100, 200]} /> <Confetti cone amount=20 x={[-1, 1]} y={[0, 1]} delay={[0, 550]} colorRange={[200, 300]} />
<Confetti noGravity x={[-1, 1]} y={[-1, 1]} delay={[0, 50]} duration=1000 colorRange={[0, 120]} /> <Confetti noGravity x={[-1, 1]} y={[-1, 1]} delay={[550, 550]} duration=1000 colorRange={[120, 240]} /> <Confetti noGravity x={[-1, 1]} y={[-1, 1]} delay={[1000, 1050]} duration=1000 colorRange={[240, 360]} />

Styling it further

We've now looked at all the different properties, but since this is just HTML and CSS you can style it further however you like. Let's look at some fullscreen examples. Having the effect fullscreen is not a simple toggle, but it is a simple bit of CSS.

<div style="
 position: fixed;
 top: -50px;
 left: 0;
 height: 100vh;
 width: 100vw;
 display: flex;
 justify-content: center;
 overflow: hidden;
 pointer-events: none;">
 <Confetti x={[-5, 5]} y={[0, 0.1]} delay={[500, 2000]} infinite duration=5000 amount=200 fallDistance="100vh" />
</div>

The element is fixed and placed just off screen so we can't see the confetti spawn in. The fallDistance property is set to 100vh so they cover the entire screen.

One thing you may have noticed is that if you click a button the previous confetti disappears immediately and new ones spawn in. We could change this by creating a new component for each click. Check out the code for this example in the REPL.

Click in me




You could also further style the confetti itself. Don't like the animation? Do it yourself! Target the confetti with :global(.confetti) and change the animation using animation-name, all values are set as css variables so you can easily use them yourself.

Properties

This is a list of all configurable properties.

Property Default Description size 10
The max size in pixels of the individual confetti pieces.
x [-0.5, 0.5]
The max horizontal range of the confetti pieces. Negative is left, positive is right. [-1, 1] would mean maximum of 200px left and 200px right.
y [0.25, 1]
The max vertical range of the confetti pieces. Negative is down, positive is up. [-1, 1] would mean maximum of 200px down and 200px up.
duration 2000
Duration of the animation for each individual piece.
infinite false
If set to true the animation will play indefinitely.
delay [0, 50]
Used to set a random delay for each piece. A large difference between each number will mean a longer spray time.
colorRange [0, 360]
Color range on the HSL color wheel. 0 to 360 is full RGB. 75 To 150 would be only green colors.
colorArray []
Can be used to pick a random color from this array. Set just one array elements to have a single color. Accepts any viable css background property, including gradients and images.
amount 50
Amount of particles spawned. The larger your spray the more pieces you might want. Be careful with too many as it might impact performance.
iterationCount 1
How many times the animation will play before stopping. Is overwritten by the "infinite" property.
fallDistance "100px"
How far each piece falls. Accepts any css property, px, rem, vh, etc, but not 0.
rounded false
Set to true to make each confetti piece rounded.
cone false
Set to true to make the explosion appear in a cone like shape which might feel more realistic when dealing with a larger amount.
noGravity false
Set to true to make the particles accelerate at a constant speed without "falling" down. Give it a more explosion like effect.
xSpread 0.15
A number from 0 to 1 that determines how far the particles spread horizontally. A low number will mean the x near the peak and the x near the end are similar.
destroyOnComplete true
By default the elements are removed when the animation is complete. Set to false to prevent this behaviour.
disableForReducedMotion false
Disable animations for those with reduced motion preferences.