How to create a confetti effect in CSS
Tags: css, webdev
Published: 2022-10-26 19:12:12

**Written by [Onuorah Bonaventure](https://blog.logrocket.com/author/onuorahbonaventure/)✏️**

Adding a confetti effect to a website usually implies installing a package. What if we could create one for ourselves using nothing but pure, unadulterated CSS and HTML? Well, we’re going to do just that! 

In this article, we are going to learn how to create a confetti effect with CSS. We’ll go over how to make different shapes, including squares, rectangles, hexagrams, pentagrams, decagrams, and wavy lines in CSS, as well as learn to animate the shapes and randomize their characteristics to create a confetti effect.

*   [Setting up our files](#setting-up-files)
*   [Creating different styles of confetti with CSS](#creating-different-styles-confetti-css")
*   [Creating the different confetti shapes](#creating-different-confetti-shapes)
    *   [Creating a square](#creating-square)
    *   [Creating a rectangle](#creating-rectangle)
    *   [Creating a hexagram](#creating-hexagram)
    *   [Creating a pentagram](#creating-pentagram)
    *   [Creating a dodecagram](#creating-dodecagram)
    *   [Creating a wavy line with CSS](#creating-wavy-line-css)
*   [Animate shapes with a waterfall effect](#animate-shapes-waterfall-effect)
*   [Randomizing shapes, animations, duration, and color](#randomizing-shapes-animation-duration-color)
*   [Bonus styles](#bonus-styles)

## Setting up our files <a name="setting-up-files">

The first thing we are going to do is create a folder on our machine. I called mine `app`, but you are free to name yours the way you like. 

Open the folder with the code editor of your choice. Next, create two files inside the folder named `index.html` and `style.css`. 

The `index.html` file will have this starter markup:

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="style.css" />
    <title>Confetti</title>
  </head>
  <body>
    <label for="check">Check to stop</label>
    <input type="checkbox" id="check" />

    <div class="confetti-container">
      <div class="confetti">
        <i class="square"></i>
        <i class="rectangle"></i>
        <i class="hexagram"></i>
        <i class="pentagram"></i>
        <i class="dodecagram"></i>
        <i class="wavy-line"></i>
      </div>
    </div>
  </body>
</html>
```

In the markup above, we have some meta tags, a title, and a link to our CSS file in the `head` tag. The body element contains a label and a check box that will only be used for demonstration purposes. 

The `confetti-container` class contains the `confetti`, and the `confetti` contains various `i` tags with classes that match the shapes we will create.

## Creating different styles of confetti with CSS <a name="creating-different-styles-confetti-css">

To create the different styles of the confetti, we will open the `style.css` file. 

Before we create the shapes, the first elements to target are `root`, `body`, `html`, `label`, and `input`. We will add the following styles to `root` and `html`:

```css
:root {
  --bg: yellow;
}

html,
body {
  background-color: #101e35;
  font-size: 10px; /* Makes 1rem = 10px */
}
```

The `label` and `input` come next:

```css
label {
  color: white;
  font-size: 1.5rem;
}
input {
  width: 40px;
  height: 40px;
  cursor: pointer;
}
```

And then we set the following styles for `.confetti-container` and `.confetti`:

```css
.confetti-container {
  user-select: none;
  pointer-events: none;
  z-index: 10;
}

.confetti {
  position: fixed;
  left: 0;
  right: 0;
  display: flex;
}
```

Let's break this down a bit. 

`user-select` and `pointer-events` ensure that the content of `.confetti-container` cannot be highlighted by the user. 

Then, `z-index` ensures that the content of the `.confetti-container` remains above every element on the page. 

The style in `.confetti` ensures that the confetti will behave separately from the other content on the page. The `display` is set to ensure that the content of `.confetti` is always stacked horizontally.

## Creating the different confetti shapes <a name="creating-different-confetti-shapes">

Now, we’ll go over how to create different shapes for our confetti effect. We do this to help add some variety to the confetti effect!

### Creating a square <a name="creating-square">

To create a square, we will select the `.square` class and add the following style to it:

```css
.confetti .square {
  width: 1rem;
  height: 1rem;
  background-color: var(--bg);
  transform: rotate(140deg);
}
```

`var(--bg)` is an example of a CSS variable. This was set in the `:root`, however, it will also be set directly in the HTML in each shape. 

The `transform` property is used to rotate the square.

### Create a rectangle <a name="creating-rectangle">

A rectangle is similar to a square, however, the width and height won’t be the same. The following styles will generate a rectangle:

```css
.confetti .rectangle {
  width: 1rem;
  height: 0.5rem;
  background-color: var(--bg);
}
```

### Creating a hexagram <a name="creating-hexagram">

`.hexagram` is a star that has six sides. The following code will generate one for us:

```css
.confetti .hexagram {
  width: 0;
  height: 0;
  border-left: 0.5rem solid transparent;
  border-right: 0.5rem solid transparent;
  border-bottom: 1rem solid var(--bg);
  position: relative;
}

.confetti .hexagram:after {
  content: "";
  width: 0;
  height: 0;
  border-left: 0.5rem solid transparent;
  border-right: 0.5rem solid transparent;
  border-top: 1rem solid var(--bg);
  position: absolute;
  top: 0.33rem;
  left: -0.5rem;
}
```

In `.confetti .hexagram`, setting the width and height to `0`, as well as setting the borders in the same manner, ensure that we generate a triangle. The `position` element makes sure that the properties within it can be moved independently. 

In `.confetti .hexagram:after`, we generate another triangle that is reversed. And with the `position` set to `absolute`, we can set the values for `top` and `left` to correctly position and form a six-sided star.

### Creating a pentagram <a name="creating-pentagram">

To create a pentagram, we need to make a five-sided star. To do so, we will add the following styles to `.pentagram`:

```css
.confetti .pentagram {
  width: 0rem;
  height: 0rem;
  display: block;
  margin: 0.5rem 0;
  border-right: 1rem solid transparent;
  border-bottom: 0.7rem solid var(--bg);
  border-left: 1rem solid transparent;
  transform: rotate(35deg);
  position: relative;
}
.confetti .pentagram:before {
  border-bottom: 0.8rem solid var(--bg);
  border-left: 0.3rem solid transparent;
  border-right: 0.3rem solid transparent;
  position: absolute;
  height: 0;
  width: 0;
  top: -0.45rem;
  left: -0.65rem;
  display: block;
  content: "";
  transform: rotate(-35deg);
}
.confetti .pentagram:after {
  position: absolute;
  display: block;
  color: var(--bg);
  top: 0.03rem;
  left: -1.05rem;
  width: 0rem;
  height: 0rem;
  border-right: 1rem solid transparent;
  border-bottom: 0.7rem solid var(--bg);
  border-left: 1rem solid transparent;
  transform: rotate(-70deg);
  content: "";
}
```

Let’s break it down. 

`.confetti .pentagram` generates a triangle and rotates it by `35deg`. 

`.confetti .pentagram:before` generates a triangle as well and rotates it by `-35deg`. The `position` was set to move the elements vertically and horizontally. 

`.confetti .pentagram:after` generates another triangle and rotates it by `70deg`. Additionally, the `position` was used to move the top and `bottom` displacement.

### Creating a dodecagram <a name="creating-dodecagram">

A dodecagram is a 12-sided star. It combines squares to form its shape. Let’s build it within our `.dodecagram` element:

```css
.confetti .dodecagram {
  background: var(--bg);
  width: 8px;
  height: 8px;
  position: relative;
}

.confetti .dodecagram:before {
  content: "";
  height: 8px;
  width: 8px;
  background: var(--bg);
  transform: rotate(30deg);
  position: absolute;
  top: 0;
  left: 0;
}
.confetti .dodecagram:after {
  content: "";
  height: 8px;
  width: 8px;
  background: var(--bg);
  transform: rotate(60deg);
  position: absolute;
  top: 0;
  left: 0;
}
```

`.confetti .dodecagram` generates a square, but `confetti .dodecagram:before` and `.confetti .dodecagram:after` generate two rotated squares.

### Creating a wavy line with CSS <a name="creating-wavy-line-css">

To create our `.wavy-line` element, we will write the following code:

```css
.confetti .wavy-line {
  position: relative;
}
.confetti .wavy-line::after,
.confetti .wavy-line::before {
  content: "";
  height: 10px;
  width: 80px;
  background-size: 20px 10px;
  position: absolute;
  left: -9rem;
  transform: rotate(90deg);
}

.confetti .wavy-line::before {
  background-image: linear-gradient(
    45deg,
    transparent,
    transparent 50%,
    var(--bg) 50%,
    transparent 60%
  );
  top: 1rem;
}
.confetti .wavy-line::after {
  background-image: linear-gradient(
    -45deg,
    transparent,
    transparent 50%,
    var(--bg) 50%,
    transparent 60%
  );
}
```

Let’s go over this in more detail. `.confetti .wavy-line`  was used to set a relative position to its content. 

In `.confetti .wavy-line::after`  and `.confetti .wavy-line::before, background-size` is used to specify the horizontal and vertical size of the pseudo-element. 

`background-image` was then used to draw the lines with their specific angles.

## Animate shapes with a waterfall effect <a name="animate-shapes-waterfall-effect">

To animate the shapes and make them simulate a waterfall, we will add the following styles:

```css
.confetti i {
  width: 3rem;
  height: 3rem;
  margin: 0 0.2rem;
  animation-name: confetti;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  animation-duration: calc(60s / var(--speed));
}

.confetti i:nth-child(even) {
  transform: rotate(90deg);
}

@keyframes confetti {
  0% {
    transform: translateY(-100vh);
  }

  100% {
    transform: translateY(100vh);
  }
}
```

Within the code, `.confetti i`  is used to select every shape and apply animation properties to it. 

`calc()` is a function used to perform calculations in CSS. 

We select `.confetti i:nth-child(even)` to rotate every shape whose index is an even number. 

Finally, under the `@keyframes confetti`, we create an animation to make the shapes move from the top to the bottom of the page.

## Randomizing shapes, animation, duration, and color <a name="randomizing-shapes-animation-duration-color">

To make the shapes fall with varying duration and have different colors, we have to pass variables directly to the shapes using HTML and then get rid of `:root` entirely:

```html
<div class="confetti-container">
      <div class="confetti">
        <i style="--bg: red; --speed: 20" class="square"></i>
        <i style="--bg: green; --speed: 24" class="rectangle"></i>
        <i style="--bg: white; --speed: 13" class="hexagram"></i>
        <i style="--bg: yellow; --speed: 10" class="pentagram"></i>
        <i style="--bg: purple; --speed: 17" class="dodecagram"></i>
        <i style="--bg: pink; --speed: 15" class="wavy-line"></i>
      </div>
</div>
```

Next, we’ll create more of these shapes, add random colors, and give them some speed to generate our confetti:

```html
<div class="confetti-container">
      <div class="confetti">
        <i style="--speed: 10; --bg: yellow" class="square"></i>
        <i style="--speed: 18; --bg: white" class="pentagram"></i>
        <i style="--speed: 29; --bg: green" class="rectangle"></i>
        <i style="--speed: 17; --bg: blue" class="hexagram"></i>
        <i style="--speed: 33; --bg: red" class="pentagram"></i>
        <i style="--speed: 26; --bg: yellow" class="dodecagram"></i>
        <i style="--speed: 24; --bg: pink" class="wavy-line"> </i>
        <i style="--speed: 5; --bg: blue" class="wavy-line"></i>
        <i style="--speed: 40; --bg: white" class="square"></i>
        <i style="--speed: 17; --bg: green" class="rectangle"></i>
        <i style="--speed: 25; --bg: white" class="square"></i>
        <i style="--speed: 18; --bg: green" class="rectangle"></i>
        <i style="--speed: 15; --bg: yellow" class="wavy-line"> </i>
        <i style="--speed: 32; --bg: yellow" class="pentagram"></i>
        <i style="--speed: 25; --bg: white" class="square"></i>
        <i style="--speed: 18; --bg: green" class="rectangle"></i>
        <i style="--speed: 37; --bg: yellow" class="dodecagram"></i>
        <i style="--speed: 23; --bg: pink" class="wavy-line"></i>
        <i style="--speed: 37; --bg: red" class="dodecagram"></i>
        <i style="--speed: 37; --bg: pink" class="wavy-line"></i>
        <i style="--speed: 36; --bg: white" class="hexagram"></i>
        <i style="--speed: 32; --bg: green" class="wavy-line"></i>
        <i style="--speed: 32; --bg: yellow" class="pentagram"></i>
        <i style="--speed: 29; --bg: white" class="square"></i>
        <i style="--speed: 18; --bg: green" class="rectangle"></i>
        <i style="--speed: 37; --bg: red" class="dodecagram"></i>
        <i style="--speed: 23; --bg: pink" class="wavy-line"> </i>
        <i style="--speed: 30; --bg: pink" class="rectangle"></i>
        <i style="--speed: 30; --bg: red" class="square"></i>
        <i style="--speed: 18; --bg: red" class="pentagram"></i>
        <i style="--speed: 19; --bg: green" class="rectangle"></i>
        <i style="--speed: 16; --bg: blue" class="hexagram"></i>
        <i style="--speed: 23; --bg: red" class="pentagram"></i>
        <i style="--speed: 34; --bg: yellow" class="dodecagram"></i>
        <i style="--speed: 39; --bg: pink" class="wavy-line"></i>
        <i style="--speed: 40; --bg: purple" class="square"></i>
        <i style="--speed: 21; --bg: green" class="rectangle"></i>
        <i style="--speed: 14; --bg: white" class="square"></i>
        <i style="--speed: 38; --bg: green" class="rectangle"></i>
        <i style="--speed: 19; --bg: red" class="dodecagram"></i>
        <i style="--speed: 29; --bg: pink" class="wavy-line"> </i>
        <i style="--speed: 21; --bg: white" class="hexagram"></i>
        <i style="--speed: 17; --bg: purple" class="wavy-line"></i>
        <i style="--speed: 32; --bg: yellow" class="pentagram"></i>
        <i style="--speed: 23; --bg: white" class="square"></i>
        <i style="--speed: 18; --bg: green" class="rectangle"></i>
        <i style="--speed: 37; --bg: red" class="dodecagram"></i>
        <i style="--speed: 48; --bg: pink" class="wavy-line"> </i>
        <i style="--speed: 38; --bg: pink" class="rectangle"></i>
        <i style="--speed: 13; --bg: red" class="pentagram"></i>
        <i style="--speed: 49; --bg: yellow" class="dodecagram"></i>
        <i style="--speed: 19; --bg: cyan" class="wavy-line"></i>
        <i style="--speed: 15; --bg: steelblue" class="square"></i>
        <i style="--speed: 10; --bg: yellow" class="square"></i>
        <i style="--speed: 18; --bg: white" class="pentagram"></i>
        <i style="--speed: 29; --bg: green" class="rectangle"></i>
        <i style="--speed: 17; --bg: blue" class="hexagram"></i>
        <i style="--speed: 33; --bg: red" class="pentagram"></i>
        <i style="--speed: 26; --bg: yellow" class="dodecagram"></i>
        <i style="--speed: 24; --bg: pink" class="wavy-line"> </i>
        <i style="--speed: 5; --bg: white" class="wavy-line"></i>
        <i style="--speed: 40; --bg: purple" class="square"></i>
        <i style="--speed: 17; --bg: green" class="rectangle"></i>
        <i style="--speed: 25; --bg: white" class="square"></i>
        <i style="--speed: 18; --bg: green" class="rectangle"></i>
        <i style="--speed: 15; --bg: cyan" class="wavy-line"> </i>
        <i style="--speed: 32; --bg: yellow" class="pentagram"></i>
        <i style="--speed: 45; --bg: white" class="square"></i>
        <i style="--speed: 18; --bg: green" class="rectangle"></i>
        <i style="--speed: 37; --bg: red" class="dodecagram"></i>
        <i style="--speed: 23; --bg: pink" class="wavy-line"> </i>
        <i style="--speed: 37; --bg: red" class="dodecagram"></i>
        <i style="--speed: 37; --bg: pink" class="wavy-line"> </i>
        <i style="--speed: 26; --bg: white" class="hexagram"></i>
        <i style="--speed: 32; --bg: cyan" class="wavy-line"></i>
        <i style="--speed: 32; --bg: yellow" class="pentagram"></i>
        <i style="--speed: 45; --bg: white" class="square"></i>
        <i style="--speed: 18; --bg: green" class="rectangle"></i>
        <i style="--speed: 37; --bg: red" class="dodecagram"></i>
        <i style="--speed: 23; --bg: pink" class="wavy-line"> </i>
        <i style="--speed: 50; --bg: pink" class="rectangle"></i>
        <i style="--speed: 30; --bg: red" class="square"></i>
        <i style="--speed: 18; --bg: red" class="pentagram"></i>
        <i style="--speed: 19; --bg: green" class="rectangle"></i>
        <i style="--speed: 16; --bg: blue" class="hexagram"></i>
        <i style="--speed: 23; --bg: red" class="pentagram"></i>
        <i style="--speed: 33; --bg: yellow" class="dodecagram"></i>
        <i style="--speed: 39; --bg: white" class="wavy-line"></i>
        <i style="--speed: 40; --bg: orange" class="square"></i>
        <i style="--speed: 21; --bg: green" class="rectangle"></i>
        <i style="--speed: 14; --bg: white" class="square"></i>
        <i style="--speed: 38; --bg: green" class="rectangle"></i>
        <i style="--speed: 19; --bg: red" class="dodecagram"></i>
        <i style="--speed: 29; --bg: pink" class="wavy-line"> </i>
        <i style="--speed: 34; --bg: white" class="hexagram"></i>
        <i style="--speed: 17; --bg: indigo" class="wavy-line"></i>
        <i style="--speed: 32; --bg: yellow" class="pentagram"></i>
        <i style="--speed: 23; --bg: white" class="square"></i>
        <i style="--speed: 18; --bg: green" class="rectangle"></i>
        <i style="--speed: 37; --bg: red" class="dodecagram"></i>
        <i style="--speed: 48; --bg: pink" class="wavy-line"> </i>
        <i style="--speed: 38; --bg: pink" class="rectangle"></i>
        <i style="--speed: 13; --bg: red" class="pentagram"></i>
        <i style="--speed: 49; --bg: yellow" class="dodecagram"></i>
        <i style="--speed: 19; --bg: purple" class="wavy-line"></i>
        <i style="--speed: 15; --bg: cyan" class="square"></i>
    </div>
</div>
```

You can see the final result of our CSS confetti effect in the CodePen below:

See the Pen [CSS Confetti](https://codepen.io/bonarhyme/pen/ExLZgdE) by Onuorah Bonaventure Chukwudi ([@bonarhyme](https://codepen.io/bonarhyme)) on [CodePen](https://codepen.io).

## Bonus styles <a name="bonus-styles">

We can also include an option for the user to pause the confetti. Add the following style so that we can stop the animation when we click the checkbox:

```css
input:checked + .confetti-container i {
  /* display: none; */
  animation-play-state: paused;
}
```

You can also specify the dimension of the confetti using this style:

```css
.confetti {
  position: fixed;
  left: 0;
  right: 0;
  display: flex;
  width: 600px;
  height: 600px;
  overflow: hidden;
}
```

_**N.B.**, Adding a display of `none` removes the confetti from the screen._ 

The complete code with these bonus styles can be viewed, edited, and forked on CodePen and GitHub:

See the Pen [CSS Confetti with bonus style](https://codepen.io/bonarhyme/pen/ZEoMaea) by Onuorah Bonaventure Chukwudi ([@bonarhyme](https://codepen.io/bonarhyme)) on [CodePen](https://codepen.io).

## Conclusion

Although it may have seemed daunting, we were able to create a cool confetti effect with CSS! This is all to show that CSS shouldn’t look scary and that you can tap into its superpowers to create amazing animations and layouts. 

Thank you for reading through. I hope you enjoyed this article, and be sure to leave a comment if you have any questions. Happy coding!

---
## How to create a confetti effect in CSS

As web frontends get increasingly complex, resource-greedy features demand more and more from the browser. If you’re interested in monitoring and tracking client-side CPU usage, memory usage, and more for all of your users in production, try [LogRocket](https://lp.logrocket.com/blg/signup).

[![LogRocket sign-up](https://blog.logrocket.com/wp-content/uploads/2019/12/cpu-memory-usage.png)](https://lp.logrocket.com/blg/signup)

[LogRocket](https://lp.logrocket.com/blg/signup) is like a DVR for web and mobile apps, recording everything that happens in your web app or site. Instead of guessing why problems happen, you can aggregate and report on key frontend performance metrics, replay user sessions along with application state, log network requests, and automatically surface all errors.

Modernize how you debug web and mobile apps — [Start monitoring for free](https://lp.logrocket.com/blg/signup).