In this article, we're going to create an 80's style text effect with CSS. The effect uses multiple text-shadow
, background-clip
, filter
, linear gradients and -webkit-text-stroke
to achieve a cool metallic effect.
Before we dive into the actual CSS you probably want to see the end result.
Let's start by defining our HTML markup that we will be using.
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta http-equiv="X-UA-Compatible" content="ie=edge" /><title>Retro effect with CSS</title></head><body><div class="container"><h1 class="title"><span class="metal clip raise">Retro</span><br><span class="metal clip raise">effect</span></h1><h2 class="subtitle">With CSS</h2></div></body></html>
The HTML markup has a container div
element and two header elements. The h1
element has two span
elements that have the text Retro and effect. The text is split into to span
elements so we can apply the effect to both of them individually.
The container
, title
and subtitle
classes define mostly positioning rules so we won't be covering them. You can find the full CSS code in the GitHub repo.
The span
elements have two classes that we will use to define our effect. Let's create the metallic fill for the text by adding a metal
CSS class.
Add the following code inside the head
tags in the HTML.
<style type="text/css">.metal {background: linear-gradient(hsl(239, 50%, 30%) 15%,hsl(239, 50%, 40%) 25%,hsl(200, 60%, 50%) 35%,hsl(100, 70%, 80%) 45%,hsl(60, 100%, 98%) 50%,hsl(240, 0%, 0%) 52%,hsl(240, 10%, 10%) 60%,hsl(240, 50%, 30%) 70%,hsl(220, 70%, 60%) 80%,hsl(212, 92%, 76%) 85%);}</style>
This will define a background for our text consisting of a linear gradient with ten colors. The output will look like this.
The gradient goes from darker blue to a greenish almost white, then there's a hard transition to black and a gradient to ligh blue. This creates an effect of metallic reflection and shine.
But how do we use the gradient as fill for the text and not a background? This can be done using the background-clip
rule. Let's add the following rules to our .metal
class.
.metal {/* ... */color: transparent;background-clip: text;-webkit-background-clip: text;}
background-clip: text
creates a clipping mask from the text and uses it as a mask when rendering the background. Only the area of the clipping mask is rendered. The text itself is also rendered, so we need to add color: transparent
to prevent it from covering the background. For this to work on WebKit-based browsers we need to add -webkit-background-clip: text
.
Next, as a polish 😜, we'll add a border to the text. If we would just add border: ...
we would get a box-shaped border for the whole element, which is not what we want. 🤔
Luckily, there's a non-standard CSS rule -webkit-text-stroke
which is supported by all the major browsers except IE. Firefox and Edge support the webkit
prefix version and don't have their own prefix.
.metal {/* ... */-webkit-text-stroke: 2px hsl(200, 65%, 80%);}
Nice! The only thing we have left is to add the 3D effect. We can achieve the effect by using a neat trick of stacking multiple shadows with increasing offset and changing color at every level of the stack. CSS has the text-shadow
rule which we could use but unfortunately, it doesn't work well with background-clip
because the shadow is drawn over the background 😔
But the CSS Filter effects also have a drop-shadow
filter which we can use.
Let's add a new class raise
to our CSS with the filter
rule, that contains 5 drop-shadow
filters for the 3D effect and one extra for an actual shadow.
.raise {filter: drop-shadow(1px 3px 0px hsl(242, 54%, 10%))drop-shadow(1px 3px 0px hsl(242, 54%, 15%))drop-shadow(1px 3px 0px hsl(242, 54%, 20%))drop-shadow(1px 3px 0px hsl(242, 54%, 25%))drop-shadow(1px 3px 0px hsl(242, 54%, 30%))drop-shadow(0px 0px 10px rgba(16, 16, 16, 0.4));}
We're using the same color with increasing luminosity to create a gradient effect. Because of the way the filter effects work, the offsets all have the same value. When we add multiple drop-shadow
filters, each subsequent shadow uses the result of the previous one as the shadow outline. So we keep the offset at 3px
it will increase by 3px
on each step.
The With CSS
text in the CodeSandbox demo uses two text-shadows
to achieve its blue and yellow shadows.
I've left out the font and positioning CSS rules for simplicity.
.subtitle {/* ... */transform: rotateZ(-10deg);color: hsl(318, 100%, 51%); /* pink */text-shadow: -2px -3px hsl(53, 100%, 81%) /* yellow */, 5px 5px hsl(240, 90%, 61%); /* blue */}
Learn more
MDN on background-clip
MDN on text-shadow
CSS-Tricks article on filter effects
CSS-Tricks article on -webkit-text-stroke