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 neon text. Each title flickers on and off reminsicent of a neon sign. The text is ebullient with bright, saturated colours. The palette is blue, pink, and turquoise that was so prominent in the 80’s. It is backed a trendy rock track by Starship.

You can watch the full title sequence on YouTube.

The title card for Cocktail

The title card looks like the sign for a bar. The text is in blue and it is surrounded by a pink ring. Looking at it through today’s lens, it looks like a subpar design! I will resist reworking anything!

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.

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 nymph, I thought that a single shadow with a large blur radius would suffice:

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

/* other styles */
}

Alas, it looks quite faint..

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

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 */
}

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.

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

@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!

h1::before {
content: “”;

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

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 ignores the shape of the element.

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, we can do similar to what we did with text-shadow. This is what it looks like:

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 core of the neon effect of the title card animation. I also animated 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 think it is 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:

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 {
10% {
opacity: 1;
}

to {
opacity: 1;
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))
drop-shadow(0 0 30px var(–ring-glow-color-outer));
}
}

@keyframes off-ring {
90% {
opacity: 1;
}

to {
opacity: 0;
filter: none;
}
}

Notice that we use filter: none; to animate out the shadows for the ring!

That’s it!

Written by Rob O’Leary

Subscribe to web feed for the latest articles.

© Rob OLeary 2024

Leave a Reply

Your email address will not be published. Required fields are marked *