Hover✨ Premium

Confetti Button

Button that fires ~100 coloured confetti on click: particles burst beyond the button edges, fall under gravity and bounce, computed on a JS canvas.

JSCanvasAnimation

Updated

This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Hover has 48 effects, including 5 free. Explore the category →

3 usage examples

Contest entry validation — community campaign for a ski gear brand — Confetti Button example 1

① Contest entry validation — community campaign for a ski gear brand

WhenThe "Enter now!" button triggers a confetti burst spilling over the card's edges when clicked, celebrating the contest entry.
WhyA spatial celebration that overflows the button creates a memorable, festive moment — far more impactful than an animation confined inside the element.
Settings200×56 px button on a white background. Confetti in brand colours (edit the colors array in the JS). Overflow area kept clear in the layout (overflow visible on the parent).
Module completion in a learning path — microlearning platform of a training organisation — Confetti Button example 2

② Module completion in a learning path — microlearning platform of a training organisation

WhenThe "Module done!" button fires confetti on the last quiz's validation, rewarding progress.
WhyA confetti burst that overflows the button creates a memorable celebration moment that motivates continuing the learning path — more effective than a plain congratulations message.
SettingsDark platform background, vibrant confetti (yellow, green, pink). 220×60 px centred button. The button can trigger navigation to the next module after a 1.5 s delay, giving confetti time to show.
First review published — community section of a craft marketplace — Confetti Button example 3

③ First review published — community section of a craft marketplace

WhenThe "Publish my review" button triggers confetti for a user's very first review, celebrating their entry into the community.
WhyA first review deserves celebrating; the confetti create a memorable onboarding moment that encourages coming back to contribute.
Settings180×52 px button. Warm-tone confetti (ochre, terracotta, sage green) to match the crafts aesthetic. Overflow area unmasked on the card.

How it works

The .fx-0370-root frame holds a canvas positioned with overflow (position: absolute; top: -220px; left: -180px) and a button. The canvas is resized in JavaScript to cover a large area around the button without enlarging the DOM: its width and height are computed from devicePixelRatio to stay sharp on Retina screens. The canvas carries aria-hidden="true"; the confetti are purely decorative.

When the button is clicked, burst() creates ~100 particle objects with random position, velocity, colour and rotation. Each requestAnimationFrame frame clears the canvas, applies gravity (vy += 0.4 px/frame), a floor bounce with damping (vy *= −0.5), and slight horizontal friction. Particles disappear when their opacity reaches zero (it decreases by 0.015 per frame). The loop stops when all particles have gone. An IntersectionObserver pauses the loop when the component leaves the screen.

Under prefers-reduced-motion: reduce, burst() creates no particles; the button remains functional but without animation. The button itself has a visible :focus-visible outline and can be activated by keyboard.

Accessibility

  • Reduced motion: under prefers-reduced-motion: reduce, no animated confetti is created. The button still gives visual feedback: its background briefly turns green for 1.2 s to confirm the click. No particles are drawn.
  • Decorative canvas: the canvas carries aria-hidden="true"; the confetti convey no information and are ignored by assistive technologies.
  • Native button: the <button> element is focusable by Tab, activatable by Enter or Space, and correctly announced by screen readers. Its label can be freely customised.
  • No information reserved to the visual: the confetti rain is a visual celebration; it does not gate access to a feature. The business action (validation, sign-up…) must be confirmed by another means (text message, confirmation page).

Browser compatibility

2D canvas + 2.8 KB of JavaScript, no dependency. Confetti are computed in pure JS, with no animation library. IntersectionObserver is available since Chrome 51, Firefox 55 and Safari 12.1; without it, the loop also runs off screen. devicePixelRatio is available in all modern browsers. Measured in Chromium 151, Firefox 153 and WebKit 26: burst, gravity and bounce identical in all three.

Chrome 51+✓ Full
Firefox 55+✓ Full
Safari 12.1+✓ Full
Edge 79+✓ Full
Mobile iOS 12.2+✓ Full
Android Chrome 51+✓ Full

Without JavaScript, the canvas stays empty and the button renders without effect. Without IntersectionObserver (browsers before 2018), the loop also runs off screen — negligible CPU impact since the loop stops naturally when all particles have gone.

The code

HTML structure to paste into your page (the CSS + JS come with your purchase):

index.html — structure
<div class="fx-0370-root">
  <div class="mi-confetti-scene">
    <div class="mi-confetti-wrap">
      <canvas class="mi-confetti-canvas" aria-hidden="true"></canvas>
      <button class="mi-confetti-btn">Celebrate!</button>
    </div>
  </div>
</div>

One-time payment, no subscription — the code is yours forever

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
Confetti colours (JS — colors array) festive multi-colour palette (red, orange, yellow, green, blue, purple, pink) Replace with your brand colours. Fewer colours gives a more subtle look; a single colour creates a monochrome effect.
Number of confetti (JS — count = 100) 100 particles Lower to 50 for a lighter, less CPU-intensive effect; raise to 200 for a denser burst. Beyond 300, the performance impact becomes noticeable on mobile.
Gravity (JS — vy += 0.4) 0.4 px/frame Lower to 0.2 for slowly floating confetti; raise to 0.8 for a fast fall. The value is in pixels per frame — on a 120 Hz screen the confetti fall twice as fast.
Button label (HTML — content of .mi-confetti-btn) "Celebrate!" Replace with "Enter now!", "Done", "Submit" or any contextual label. The button sizes itself automatically.
Confetti size (JS — particle w and h) width 6-10 px, height 3-6 px (random) Raise the max values for larger, more visible pieces; lower them for a "dust" effect.

FAQ

The canvas is positioned absolute with top: -220px; left: -180px and deliberately overflows neighbouring elements. That is the intended effect: confetti invade the space around the button. Make sure the component's direct parent does not have overflow: hidden.
Yes. Call the burst(canvas, ctx) function directly within the instance's scope. To access it from the outside, add root.dataset.burst = 'ready' in the JS and assign the reference on creation so that root._burst() can be called externally.
Yes. Each particle has a lifespan set by its opacity decay (−0.015 per frame, about 4 s at 60 Hz). When all particles are gone, the requestAnimationFrame loop stops and the CPU is no longer used.