js-confetti

A zero-dependency JavaScript library for canvas-based confetti animations, including emoji confetti support.

Library
npm
v0.13.1
1,295stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
40/100Fair
Development Activity0
Maintenance20
Community40
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
63/100Good
Architecture72
Code Quality45
Innovation80
Learning Curve55

js-confetti is a lightweight, zero-dependency JavaScript library for rendering confetti animations directly on an HTML5 canvas. It ships with sensible defaults so it works with a single line of code, while still exposing configuration for confetti color, radius, count, and dispatch position through methods like addConfetti() and addConfettiAtPosition().

Beyond plain colored confetti, the library supports emoji confetti — swapping the canvas-drawn ellipses for rendered emoji characters — and includes TypeScript typings out of the box. Confetti speed automatically adapts to the screen width so the effect looks consistent whether it fires on a small mobile viewport or an ultra-wide desktop display.

What You Get

  • A JSConfetti class that creates and manages its own canvas element automatically, or accepts a custom canvas via the constructor.
  • An addConfetti() method for full-screen confetti bursts fired from both sides of the viewport.
  • An addConfettiAtPosition() method for triggering confetti from a specific x/y coordinate, such as a mouse click.
  • A clearCanvas() method to stop all active confetti immediately, and destroyCanvas() to remove the canvas element entirely.
  • Emoji confetti support via the emojis config option, with a configurable emojiSize.

Common Use Cases

  • Celebrating a user completing a checkout, signup, or onboarding flow with a confetti burst.
  • Firing confetti from the exact point a user clicked, such as a ‘like’ or ‘claim reward’ button.
  • Adding festive emoji confetti (hearts, stars, etc.) for a themed celebration screen.
  • Awaiting the addConfetti() promise to sequence follow-up UI, such as showing a modal only after the confetti animation finishes.

Under The Hood

Architecture The library is organized as a small layered hierarchy: the public JSConfetti class owns a requestAnimationFrame loop and the canvas element (created automatically or injected via constructor), each call to addConfetti()/addConfettiAtPosition() spawns a ConfettiBatch that tracks a group of ConfettiShape instances and exposes a promise resolved once every shape in the batch has left the visible canvas area, and ConfettiShape itself owns the per-particle physics — gravity, drag, rotation, and emoji-vs-color rendering — driven by small pure-function helpers (generateConfettiAngles, generateRandomNumber, fixDPR, normalizeConfettiConfig) for config normalization and math. The animation loop throttles expensive visibility cleanup to every tenth iteration for performance. There’s no dependency injection or external state container — each JSConfetti instance is a self-contained mutable object — and the physics constants and positional math are tightly coupled between JSConfetti and ConfettiShape, so changing the core shape abstraction would require touching both.

Tech Stack Written in TypeScript targeting ES6, compiled with Rollup (rollup-plugin-typescript2, @rollup/plugin-babel, rollup-plugin-terser) into a minified UMD bundle, an ESM build, and standalone .d.ts typings, with zero runtime dependencies. The demo site under site/ is built separately with Webpack 5 and Babel (React/JSX presets) for the live GitHub Pages demo. Linting runs on ESLint 9 with typescript-eslint’s flat config. Deployment is purely a published npm package plus a jsDelivr CDN build and a static demo site — no server component.

Code Quality No test files exist anywhere in the repository, and there is no CI workflow configured — testing and quality gating rely entirely on TypeScript’s strict mode (strict: true, noImplicitAny) and ESLint. Error handling is minimal: a couple of console.error() calls in normalizeConfettiConfig() flag deprecated config keys, but no exceptions are thrown elsewhere. Naming is consistent and highly descriptive (e.g. generateConfettiInitialFlightAngleFiredFromLeftSideOfTheScreen), and shared shapes are centralized in a dedicated types.ts, but the combination of no tests and no CI leaves regressions to be caught manually.

What Makes It Unique The public API is deliberately tiny — a zero-argument constructor and four methods, each taking a flat, fully-optional config object with computed defaults — so a working confetti burst is a single line of code. It handles backward compatibility gracefully: deprecated option names (emojies, confettiesNumber) still work but log a console warning steering callers to the corrected spelling, a small but thoughtful developer-experience touch rarely seen in comparably small libraries. Confetti velocity also scales with a log-based function of canvas width, so the same defaults look right on both a phone and an ultra-wide monitor without any consumer-side tuning.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search