Booking for Q1
Webflow Tutorial

How to Add a Confetti Animation When a Vimeo Video Starts Playing

How to Add a Confetti Animation When a Vimeo Video Starts Playing
Blog author Casey Lewis CL Creative
Casey Lewis
February 23, 2026

Table of contents

Book a Strategy call
We’ll confirm fit, outline options, and decide on next steps.

There's something about confetti that just works. It's celebratory, unexpected, and when it's timed right, it feels like the page is reacting to something the user did. Not just decoration sitting on a screen.

This post walks you through how to trigger a canvas confetti animation the moment a Vimeo video starts playing. We'll use the Vimeo Player API to hook into the play event, wait a beat, then fire the confetti. The result feels intentional and polished rather than random.

If you haven't worked with the Vimeo Player API before, I wrote a full breakdown of the basics here. This post will cover enough to get you up and running on its own, but that one goes deeper on the fundamentals.

What You're Building

A Vimeo video plays. About a third of a second later, confetti bursts across the screen. That's it. Simple concept, but the implementation has a few moving parts worth understanding.

Here's what you need:

  • A Vimeo video embedded on your page
  • The Vimeo Player SDK loaded via CDN
  • The canvas-confetti library loaded via CDN
  • A small JavaScript block wiring them together

Loading Your Dependencies

Add both of these script tags before your closing </body> tag. Order matters here. Both need to be available before your script runs.

<script src="https://cdn.jsdelivr.net/npm/canvas-confetti@1.9.2/dist/confetti.browser.min.js"></script>
<script src="https://player.vimeo.com/api/player.js"></script>

Setting Up Your Vimeo Iframe

Place your Vimeo iframe on the page and give it an ID. That ID is how your JavaScript will find it.

<iframe
  id="my-video"
  src="https://player.vimeo.com/video/YOUR_VIDEO_ID?h=YOUR_HASH"
  frameborder="0"
  allow="autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media"
  allowfullscreen>
</iframe>

If you want the video to autoplay when the page loads, add muted=1&autoplay=1 to the URL. Browsers block autoplay with sound by default, so muted is required for it to work.

Creating the Player Instance

Once the SDK is loaded and the iframe is on the page, you create a player instance by passing the iframe element to Vimeo.Player:

const iframe = document.getElementById('my-video');
const player = new Vimeo.Player(iframe);

You now have a JavaScript object that can communicate with the embedded video.

Hooking Into the Play Event

The Vimeo Player API fires a play event every time the video starts or resumes playing. You listen for it using player.on():

player.on('play', function() {
    // this runs every time the video plays
});

This is the hook. Instead of guessing when the video starts or using a timer from page load, you're reacting to the actual moment playback begins. That's what makes the timing feel right.

Why a 300ms Delay Before the Confetti

You could fire the confetti the instant the play event fires. But in practice, firing it immediately can feel slightly off. The video frame is just starting to render, the browser is doing a few things at once, and the confetti ends up competing for attention before the video has had a chance to settle.

A 300ms delay gives the video just enough time to actually start showing on screen. By the time the confetti fires, the video is visible and playing, so the celebration feels like a reaction to something rather than something that happened alongside it. It's a small thing but it makes a noticeable difference to how polished the interaction feels.

player.on('play', function() {
    setTimeout(function() {
        confetti({
            particleCount: 150,
            spread: 80,
            origin: { y: 0.4 },
            zIndex: 9999
        });
    }, 300);
});

Controlling the Confetti

The canvas-confetti library gives you a few key options worth knowing:

particleCount controls how many confetti pieces fire. 150 is a solid burst without being overwhelming. Crank it up to 300 for something more dramatic, drop it to 80 for something subtle.

spread controls how wide the burst fans out. 80 gives you a natural arc. Higher numbers spread it wider across the screen.

origin controls where the burst comes from. The default is the center of the screen. { y: 0.4 } pushes it slightly above center, which tends to look better when there's content below it.

zIndex makes sure the confetti renders on top of everything else on the page. 9999 is a safe bet.

One Thing to Watch Out For

The play event fires every time the video plays, not just the first time. If your user pauses and resumes the video, the confetti fires again. For a lot of use cases that's fine. But if you only want it to fire once, you can remove the confetti listener after the first time it runs.

The way to do that is with player.off(). When you register a listener with player.on(), Vimeo stores a reference to that specific function internally. player.off() tells Vimeo to find that function and deregister it. After that, the event still fires when the video plays, but there's nothing listening for it anymore.

For this to work, the function needs a name. If you write it as an anonymous function, you have nothing to pass to player.off() and no way to remove it. By naming it onPlay, you can pass that same reference to both player.on() and player.off():

function onPlay() {
    setTimeout(function() {
        confetti({
            particleCount: 150,
            spread: 80,
            origin: { y: 0.4 },
            zIndex: 9999
        });
    }, 300);

    // Remove this listener so confetti only fires once
    // The video will still play normally — this only stops the confetti
    player.off('play', onPlay);
}

player.on('play', onPlay);

The comments in the code do the heavy lifting here. Anyone reading this later knows exactly what player.off() is doing and why it's there. Without them, it reads like a line that came from nowhere.

The Full Code

Here's everything together in one clean block. If you're working in Webflow, add the two CDN script tags and this script block before your closing </body> tag:

window.Webflow = window.Webflow || [];
window.Webflow.push(function() {

    const iframe = document.getElementById('my-video');
    const player = new Vimeo.Player(iframe);

    function onPlay() {
        setTimeout(function() {
            confetti({
                particleCount: 150,
                spread: 80,
                origin: { y: 0.4 },
                zIndex: 9999
            });
        }, 300);

        // Remove this listener so confetti only fires once
        // The video will still play normally — this only stops the confetti
        player.off('play', onPlay);
    }

    player.on('play', onPlay);

});

Clean, readable, and the confetti only fires once no matter how many times the user interacts with the video.

This Is the Kind of Detail That Sticks

Confetti is small. But small interactions done well are what separate a website that feels professionally built from one that just looks professionally built.

The Vimeo Player API makes it possible to react to what's actually happening in the video rather than guessing with timers. Combined with canvas-confetti, you can add moments of delight that feel earned rather than random.

If you want to go deeper on the Vimeo Player API itself, including how to control multiple videos on the same page, read How to Use the Vimeo Player API to Control Video on Your Website.

If you're building something like this for your business and want to talk through the approach, I offer free strategy sessions. We can look at what you're working on and figure out the best way to bring it to life. Book a call here.

Claim Your Design Spot Today

We dedicate our full attention and expertise to a select few projects each month, ensuring personalized service and results.

Web design portfolio