Eurovision Gradients

Mads Stoumann - May 8 - - Dev Community

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, 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.

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

Now, for the columns, we'll create a bunch of <b>-tags (can be any tag, basically), and add some 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;
}
Enter fullscreen mode Exit fullscreen mode

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

@keyframes Y {
  to { background-position-y: 250%; }
}
Enter fullscreen mode Exit fullscreen mode

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

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. */
}
Enter fullscreen mode Exit fullscreen mode

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

.span-2 { grid-column: span 2; }
.span-3 { grid-column: span 3; }
.span-4 { grid-column: span 4; }
/* etc. */
Enter fullscreen mode Exit fullscreen mode

Let's see how we're doing:

yellow

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

.header {
  --c1: purple;
  --c2: deeppink;
  --c3: hotpink;
}
Enter fullscreen mode Exit fullscreen mode

Purple

Nice! I added a gradient text as well:

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;
}
Enter fullscreen mode Exit fullscreen mode

Now, for the red/blue-version, I took one of the nice linear() timing-functions from Adam Argyle's Open Props:

.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 );
}
Enter fullscreen mode Exit fullscreen mode

And we get:

Red Shift


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

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .