Atmosphere✨ Premium

Fireworks

One button fires 3 staggered DOM rockets that climb and burst into 30–50 colored sparks each — Web Animations API, zero canvas, zero persistent rAF loop.

JSCelebration

You'll get access to the interactive demo with a free account.

This effect is part of Effect.Labs — 811 vanilla effects, some free, some premium. Atmosphere has 57 effects, including 10 free. Explore the category →

3 usage examples

Hero / Landing — Product launch page — Fireworks example 1

① Hero / Landing — Product launch page

WhenOn a product go-live, a major update, or a countdown expiry — the visitor hits the launch button.
WhyThree rockets staggered by 200 ms create a euphoric visual moment at zero network cost (no image, no library). The container's dark gradient background integrates naturally into a dark hero.
Settings3 rockets by default, 7-color rainbow palette. To customize: replace the fireworkColors array with your brand colors before the addEventListener call.
Product component — Congratulations card in a dashboard — Fireworks example 2

② Product component — Congratulations card in a dashboard

WhenA key milestone is reached in the app (100 customers, first recurring revenue, sprint goal validated) and a celebration modal or card appears.
WhyFires only on click — never on load. The effect rewards the confirmation action without disrupting the normal workflow. Particles self-remove in ≤ 1.2 s.
SettingsReduce to 2 rockets (f < 2), brand palette e.g. ['#6366f1','#8b5cf6','#d946ef'], trail 300 ms for a snappier response.
Event end screen — Full-screen New Year fireworks — Fireworks example 3

③ Event end screen — Full-screen New Year fireworks

WhenWhen a countdown expires (New Year, livestream close, virtual conference finale) and the screen enters full-screen celebration mode.
WhyThe container fills the entire surface: rockets climb the full height and explosions spread without being clipped. With 5 staggered rockets the effect delivers its maximum visual punch — the context where DOM rockets and 30–50 sparks per burst shine most.
SettingsIncrease to 5 rockets (f < 5), extended festive palette (white, gold, red, cyan), trail duration 450 ms for a more dramatic climb, 35–55 particles per burst (particleMin: 35, particleRange: 20).

How it works

The effect runs entirely on the Web Animations API (element.animate()) and DOM <div> elements — no <canvas>, no permanent requestAnimationFrame. A click on #fireworksBtn launches three rockets staggered by 200 ms (setTimeout(fn, f * 200)). The X starting position is sampled randomly within the central 80% of the container via getBoundingClientRect(); Y is fixed at 30 px from the bottom.

Each rocket is a <div> (.firework-trail) animated from startY to targetY (between 40 and 120 px from the top) over 400 ms with an ease-out easing. When the animation ends (.onfinish), the trail is removed from the DOM and the explosion fires immediately at the same coordinate.

The explosion creates between 30 and 50 particle <div>s (.firework) positioned at the target. Dispersion angles are evenly distributed over 2π ((2π / particleCount) × i + jitter ≤ 0.5 rad) for a uniform spread. Radial velocity ranges from 50 to 130 px. Motion follows cubic-bezier(0, 0.5, 0.5, 1) — fast exit, soft arrival — simulating gravity deceleration and drag. A +30 px vertical offset at the end position reproduces the gentle fall of sparks. The glow comes from a double-layer colored box-shadow on each particle.

Cleanup is fully automatic: onfinish = () => particle.remove() removes each element as soon as its animation ends (800–1200 ms). There is no object pool and no active loop between clicks — the main thread is free as soon as the last particle disappears.

Accessibility

  • prefers-reduced-motion: not handled — no matchMedia('(prefers-reduced-motion: reduce)') block exists in the code. All 3 explosions fire regardless of the OS setting. Add this check before any accessible deployment: either ignore the click or reduce to 1 rocket and 15 particles.
  • The .fireworks-btn button is a native <button> — keyboard-focusable, activatable with Enter or Space, no extra JavaScript required.
  • The .fireworks-container carries no role or aria-label. Dynamically created particle <div>s receive no screen-reader announcement — neutral for a purely decorative effect.
  • White button text on the amber-to-red gradient (perceived luminance ≈ 0.24) meets the WCAG AA contrast ratio ≥ 4.5:1.
  • No informational content is conveyed through the animation alone: application state must be communicated through other means (text, aria-live).

Browser compatibility

Requires the Web Animations API (Element.animate()) — supported in all modern browsers. Zero canvas, zero external dependencies.

Chrome 84+✓ Full
Firefox 75+✓ Full
Safari 13.4+✓ Full
Edge 84+✓ Full
Mobile iOS 13.4+✓ Touch OK
Android Chrome✓ Full

If <code>Element.animate</code> is absent (very old browsers), particles are created in the DOM but no animation plays — they appear and disappear in place without movement. No fatal JS error; the page stays functional.

The code

HTML structure to paste into your page (CSS + JS available with a premium account):

index.html — structure
<div class="fireworks-container" id="fireworksContainer">
  <button class="fireworks-btn" id="fireworksBtn">Launch!</button>
  <!-- .firework-trail and .firework: injected then auto-removed by JS -->
</div>
🔒 Unlock the full code — from €2.99 the first month

Full HTML + CSS + JS, copy-paste ready — with hundreds of premium effects.

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
fireworkColors (JS array) 7 rainbow colors Hex color array for rockets and particles. Replace it before the addEventListener call to enforce your brand palette.
Rocket loop: f < 3 3 Number of rockets per click. Change the upper bound in for (let f = 0; f < N; f++): 1 for a single shot, 5 for a festive volley.
particleCount: 30 + Math.floor(Math.random() * 20) 30–50 per rocket Particle count range per explosion. Reduce to 15 + Math.floor(Math.random() * 10) to lighten the load on slow devices.
velocity: 50 + Math.random() * 80 50–130 px Explosion radius in pixels. Increase the base (e.g. 80 + Math.random() * 120) for wider bursts.
Trail duration: 400 (ms) 400 ms Rocket climb duration. Reduce to 200 ms for an immediate explosion, raise to 700 ms for a more dramatic arc.
Particle duration: 800 + Math.random() * 400 800–1200 ms Lifespan of each spark. The random spread avoids simultaneous onfinish callbacks. Reduce to 500 + Math.random() * 200 for a crisper animation.
targetY: 40 + Math.random() * 80 40–120 px from top Explosion zone inside the container. Narrow the range (30 + Math.random() * 40) to cluster bursts at the top, or widen it to spread them across the full height.

FAQ

No — no function is published on window. To trigger from a business event (Stripe confirmation, milestone reached), call document.getElementById('fireworksBtn').click() in your callback, or extract the firing logic into a named function before binding it to the button.
Up to 3 rockets × 50 particles = 150 <div>s created then removed in ≤ 1.2 s. On slow devices, reduce the rocket count (f < 2) or the particle ceiling (20 + Math.floor(Math.random() * 10)) to stay at 60 fps.
No — the effect does not support data-attributes. Colors are defined by the fireworkColors array inside the IIFE. To customize without duplicating the whole script, expose the array as an external variable before the IIFE (let FWK_COLORS = ['#6366f1',…]) and update it from your own code on the fly.