Eurovision Gradients
Tags: css, webdev, showdev, tutorial
Published: 2024-05-08 15:20:05

So, it's _that_ time of the year, if you live in Europe: **Eurovision!** It's the world's oldest and largest song competition — that people either love, hate or love/hate!

I watched the first semifinal yesterday, and was actually blown away by the graphic design this year. Really nice, animated gradients — and a very vibrant color palette.

But … then I went to the [official website](https://eurovision.tv/), and saw a 4.6 megabyte pixelated, sad looking animated gradient! Why? When we can easily do animated gradients in CSS?

Let's dive in.

## Re-creating the gradients

If you look at the gradients — or if you watched the show — you'll notice it's basically a grid with columns that span between 1—8.

```css
.eurovision {
  aspect-ratio: 4/1;
  container-type: inline-size;
  display: grid;
  grid-auto-flow: column;
  position: relative;
  width: 100%;
}
```

Now, for the columns, we'll create a bunch of `<b>`-tags (can be any tag, basically), and add some CSS:

```css
b {
  animation: Y var(--animdur, 5s) var(--animdel, 0s) var(--animtf, linear) infinite;
  background: repeating-linear-gradient(var(--deg, 0deg), var(--c1, orange), var(--c2, hotpink), var(--c3, yellow), var(--c2, hotpink), var(--c1, orange));
  background-size: 100% 500%;
  display: block;
}
```

The animation simply moves the Y-position of the background:

```css
@keyframes Y {
  to { background-position-y: 250%; }
}
```

To create some variation, we change the `animation-delay` for the `<b>`-tags, based on their `nth-of-type`:

```css
b {
  &:nth-of-type(1) { --animdel: 50ms; }
  &:nth-of-type(2) { --animdel: 100ms; }
  &:nth-of-type(3) { --animdel: 150ms; }
  &:nth-of-type(4) { --animdel: 200ms; }
  &:nth-of-type(5) { --animdel: 250ms; }
  /* etc. */
}
```

Finally, for the column-spans, we add some modifier-classes:

```css
.span-2 { grid-column: span 2; }
.span-3 { grid-column: span 3; }
.span-4 { grid-column: span 4; }
/* etc. */
```

Let's see how we're doing:

![yellow](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f6qax1jx9eet3xeu54mu.png)

Vibrant! Now, because of the custom properties, we can just add a class with some updates to get the purple/pink-gradient:

```css
.header {
  --c1: purple;
  --c2: deeppink;
  --c3: hotpink;
}
```

![Purple](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/29759yydwygs1x9fu03g.png)

Nice! I added a gradient text as well:

```css
h1 {
  background: linear-gradient(95deg, yellow, hotpink, deeppink, orange);
  background-clip: text;
  font-family: "Hind", sans-serif;
  font-optical-sizing: auto;
  font-weight: 500;
  font-style: normal;
  font-size: 10cqi;
  letter-spacing: -0.075ch;
  place-self: center center;
  position: absolute;
  text-transform: uppercase;
  -webkit-text-fill-color: transparent;
}
```

Now, for the red/blue-version, I took one of the nice `linear()` timing-functions from Adam Argyle's [Open Props](https://open-props.style/):

```css
.red-shift {
  --c1:red;
  --c2:purple;
  --c3:blue;
  --animtf:linear( 0, .006, .025 2.8%, .101 6.1%, .539 18.9%, .721 25.3%, .849 31.5%, .937 38.1%, .968 41.8%, .991 45.7%, 1.006 50.1%, 1.015 55%, 1.017 63.9%, 1.001 );
}
```

And we get:

![Red Shift](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b0pbetm9ienr1y6kfvcx.png)

---

And that's it! Remember to vote for your favorite song, and check out the CodePen here:

{% codepen https://codepen.io/stoumann/pen/dyEbejJ %}