How to create a slick CSS animation from Cocktail

How to create a slick CSS animation from Cocktail

Let’s jump to the 80’s and create an animation with a retro feel. Cocktail!

Cocktail is a romantic comedy-drama made in 1988. If you have not heard of it, the most notably thing is that it stars a young Tom Cruise. He plays a New York City business student, who takes up bartending in order to make ends meet. Hijinks and bad fashion ensue.

TLDR

Here is the finished animation.

About the title sequence

The opening title sequence features text flickering on and off reminsicent of a neon sign. The title card has blue text surrounded by a pink ring. The aesthetic and accompanying soundtrack screams 80’s.

The title card for the film Cocktail. It is a bright neon sign with blue writing saying Cocktail surrounded by a pink ring
The title card for Cocktail

You can watch the full title sequence on YouTube.

The font used is hard to pinpoint. The closest I could find is Gillies Gothic Light. The cursive style is similar. However, it does not have many of the serifs that join adjacent letters and the flourishes that give a more nuanced perception of a neon sign. I will stick with this font and not edit the gylphs to mirror the original.

This is my recreation of the title card for the film Cocktail using the Gillies Gothic Light font. It is a bright neon sign with blue writing saying Cocktail surrounded by a pink ring
My recreation of the title card for Cocktail using the Gillies Gothic Light font.

The animation

A neon effect is created with a shadow with a blur radius. For the text, we use the text-shadow property. When I was a CSS grasshopper, I thought that a single shadow with a large blur radius would suffice:

CSS
h1 {
text-shadow: 0 0 30px blue;

/* other styles */
}

Alas, it looks quite faint…

a single text shadow with a blur radius of 30px

What you need to do is stack multiple shadows with larger and larger blur radii as below:

CSS
h1 {
text-shadow: 0 0 5px blue, 0 0 10px blue,
0 0 15px blue, 0 0 20px blue,
0 0 25px blue, 0 0 30px blue;

/* other styles */
}
mutliple text shadows with increasing blur radii

To animate a text-shadow, we can set the aforementioned text-shadow in the to block of a @keyframes. We do not set any initial state. The browser does the work to interpolate the values for each of the shadows.

CSS
h1 {
animation: flicker 2s infinite ease-in-out;

/* other styles */
}

@keyframes flicker{
to {
text-shadow: 0 0 5px blue, 0 0 10px blue, 0 0 15px blue, 0 0 20px blue, 0 0 25px blue, 0 0 30px blue;
}
}

I created the pink ring using the ::before pseudo-element. We cannot use text-shadow on it because there is no text!

CSS
h1::before {
content: "";

border-radius: 50%;
width: 70%;

/* other styles */
}

To create a shadow for the pink ring, we use the filter property with the drop-shadow() function. We do not use box-shadow because it will apply the shadow to the element’s box which is a rectangle, thus ignoring the circular shape of the element.

CSS
h1::before {
filter: drop-shadow(0 0 0 hsla(300, 97%, 60%))
drop-shadow(0 0 0 hsla(300, 97%, 60%))
drop-shadow(0 0 0 hsla(300, 97%, 60%));
}

To animate the filter, it is similar to what we did with text-shadow. This is what it looks like:

CSS
h1::before {
animation: flicker-ring 2s infinite ease-in-out;
}

@keyframes flicker-ring {
to {
filter: drop-shadow(0 0 10px hsla(300, 97%, 60%))
drop-shadow(0 0 20px hsla(300, 97%, 60%))
drop-shadow(0 0 30px hsla(300, 97%, 60%));
}
}

That is the how to animate a neon effect. I also animated the opacity in the final animation to create a staged reveal before lighting up the title.

The final part of the animation is that the title card fades out. I thought it was better to use 2 separate animations to get the desired result rather than to squash everything into a single keyframes. Since the title remains in its “lit” state for a couple of seconds, we can use an animation-delay to control this duration in the second animation.

To recap, the first animation reveals and lights up the title, the second animation leaves the “lit” state linger before it unlights and fades out the title. Here is the CSS for the animations for the ring:

CSS
h1::before {
animation-name: on-ring, off-ring;
animation-duration: var(--animation-duration), var(--animation-duration);
animation-delay: 0s, var(--delay-duration);
animation-timing-function: ease-in, ease-out;
animation-fill-mode: forwards, forwards;
animation-iteration-count: 1, 1;
}

@keyframes on-ring {
to {
filter: drop-shadow(0 0 10px var(--ring-glow-color))
drop-shadow(0 0 20px var(--ring-glow-color))
drop-shadow(0 0 30px var(--ring-glow-color));
}
}

@keyframes off-ring {
to {
filter: none;
}
}

Notice that we use filter: none; to animate out the shadows for the ring! No need to specify every drop-shadow() function!

Source code

The source code is available in this github repo.

You can check out all of the animations of this series in this codepen collection.

Tagged