Knockout text is a technique where words are clipped out of an element and reveal the background. In other words, you only see the background because the letters are knocking out holes. It’s appealing because it opens up typographic styles that we don’t get out of traditional CSS properties, like color .

While we’ve seen a number of ways to accomplish knockout text in the past, there are some modern CSS properties we can use now and even enhance the effect further, like transitions and animations. Let’s see them in action.

Mix Blend Modes

There are four blend modes that effortlessly make text cutouts: multiply , screen , darken , and lighten . Applying these to the top element of a stack of image and text, text being at top, creates the knockout design.

Even though, in most cases, either black or white is used in these blend modes to get a clear distinction between the text and the background, I prefer using a darker or lighter color instead to keep the back image slightly visible, like this:

<div class="backdrop"> <p class="text">Taitō</p> </div>

/* Background layer with an image */ .backdrop { background: url("/path/to/image.jpg") center; ... } /* Dark foreground layer, with white text, set to "multiply" mix blend mode */ .text { color: white; background: rgb(59, 2, 6); mix-blend-mode: multiply; ... }

See the Pen CSS Knockout Text by Preethi (@rpsthecoder) on CodePen.

Using a darker (or lighter) color also creates a nice “theme” going on with the image shown through the text.

The multiply blend mode keeps darker colors dark and the lighter colors let through whatever’s behind them: a black portion on the top layer will be fully opaque and white will be fully transparent.

The effects of the multiply mix blend mode.

In the above example, the white text became completely see-through while the darker color around it lets the image behind be seen only a little, as the darker shades remain unaffected.

The screen blend mode reverses the roles: darker colors create translucence while lighter shades remain light and block what’s behind.

The darken and lighten blend modes are similar to multiply and screen, respectively, except that details are lost on the portions of the back image that can be seen. Rather than mixing the shades, the modes choose the darker or the lighter shade of the two layers that are shown.

See below the difference in how the four modes have blended the colors:

/* Knockout text within a dark area */ .multiply { color: white; mix-blend-mode: multiply; background-color: rgb(59, 2, 6); } /* Knockout text within a bright area */ .screen { color: black; mix-blend-mode: screen; background-color: rgb(244, 220, 211); } /* Knockout text within a dark area that's less detailed */ .darken { color: white; mix-blend-mode: darken; background-color: rgb(59, 2, 6); } /* Knockout text within a light area that's less detailed */ .lighten { color: black; mix-blend-mode: lighten; background-color: rgb(244, 220, 211); }

See the Pen CSS Knockout Text by Preethi (@rpsthecoder) on CodePen.

Using a blend mode is the most convenient option to get a knockout text effect, because it allows us to apply additional styles that other techniques might not allow.

Let’s take a closer look at the styles we can use to enhance the knockout effect.

Shadow Blur

Adding a white/black or a light/dark text shadow to the text creates a blurred effect. For example, let’s say I add a text-shadow that’s with a large blur radius value:

.text { text-shadow: 0 0 9px white; ... }

Now the edges are less crisp and give a sort of cloudy effect:

See the Pen CSS Blurred Knockout Text by Preethi (@rpsthecoder) on CodePen.

Animation

We can even make things move around a little. For example, let’s take build on the text-shadow idea we looked at above and put some movement on it to make it appear that the text is glowing:

.text { animation: glow 3s infinite; ... } @keyframes glow { 0% { text-shadow: 0 0 10px white; } 15% { text-shadow: 2px 2px 10px rgba(255, 255, 255, 1), -2px -2px 10px rgba(255, 255, 255, 1); } 30% { text-shadow: 2px 2px 4px rgba(255, 255, 255, .7), -2px -2px 4px rgba(255, 255, 255, .7); } 50% { text-shadow: 20px 20px 50px rgba(255, 255, 255, .5), -20px -20px 50px rgba(255, 255, 255, .5); } }

See the Pen CSS knockout Text Glow Animation by Preethi (@rpsthecoder) on CodePen.

Transition

Transition is another property we can apply to our knockout text and that opens up even more interesting possibilities, like using text-indent on pseudo-classes like :hover .

Here’s how we can use transition on pseudo-classes to introduce a new element into the knockout text:

/* The knockout text */ .text { transition: text-indent .5s; ... } /* On hover, trigger the transition */ .text:hover { text-indent: 5px; transition: text-indent .5s; } /* The thing that slides in on hover */ .text:hover::before { display: inline-block; content: '✈︎'; }

See the Pen CSS Knockout Text Transition by Preethi (@rpsthecoder) on CodePen.

Background Clip

The background-clip CSS property set with the text value clips a background to the shape of its foreground text.

Using background-clip: text

<p class="text">Taitō</p>

.text { background: url("/path/to/image.jpg") center; background-clip: text; color: transparent; ... }

See the Pen Knockout Text by Preethi (@rpsthecoder) on CodePen.

The transparent text shows the image behind it that’s already cut to the shape of the text. Although this is a true knockout text approach—it literally removes the text’s surrounding background on screen—having no background left to bleed into or move over leaves little space for other effects like blur, or moving text, to take place. That’s where mix-blend-mode has an advantage.

CSS Mask

The first technique we looked at employs masking, a concept where shapes are created on a foreground layer and use color to determine how much of the shape shows the background. The black parts of the foreground hide (or “mask”) and white parts reveal the background, or vice-versa. Any gray value between black and white is treated as varying degrees of partial transparency.

CSS mask works the same way: you straight up declare an image to be the mask applied over another image and, depending on the type of the mask, we get a portion cut out. As of writing this post CSS mask is fully supported in Firefox only.

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up. Desktop Chrome Firefox IE Edge Safari 88* 53 No 85* TP* Mobile / Tablet Android Chrome Android Firefox Android iOS Safari 85* 79 81* 14.0*

Since we are looking specifically into knockout text, the mask needs to be made from text. This is a great use for SVG <mask> , which can create masks from SVG shapes and texts.

<div class="backdrop"> <p class="text"></p> </div> <svg> <defs> <mask id="m"> <rect width="100%" height="100%" fill="white" /> <text x="50%" y="75%" text-anchor="middle">Taitō</text> </mask> </defs> </svg>

/* Background layer with an image */ .backdrop { background: url("/path/to/image.jpg") center; ... } /* Dark foreground layer with masking applied */ .text { background-color: rgba(59, 2, 6, 1); mask-type: luminance; /* Referrer to an SVG mask */ mask: url("#m"); ... } svg { width: 75vw; height: 20vw; } /* SVG text inside the mask */ text { font: bolder 12vw 'Alfa Slab One'; }

See the Pen Knockout Text by Preethi (@rpsthecoder) on CodePen.

The luminance value on the mask-type property of the foreground element implements a masking mechanism where parts of this layer, corresponding to the black parts of the mask, become transparent. The parts corresponding to the white portions of the mask remain opaque. The mask property uses the url() value to designate the SVG element used for the mask.

SVG’s <mask> element creates a mask imaged from its contents. The contents I made inside the <mask> are a white rectangle ( <rect> ) and black text ( <text> ). The text, being black, brings up the portion of the image behind it to the view after masking.

Blurring, Animation, and Transition

CSS masks open up the same blur and animation effects we were able to use with mix-blend-mode .

That same glowing text from we used before applies here as well, this time applied directly to the <text> element of the SVG:

text { font: bolder 12vw 'Alfa Slab One'; animation: glow 3s infinite; } @keyframes glow { 0% { text-shadow: 0 0 10px white; } 15% { text-shadow: 2px 2px 10px rgba(255, 255, 255, 1), -2px -2px 10px rgba(255, 255, 255, 1); } 30% { text-shadow: 2px 2px 4px rgba(255, 255, 255, .7), -2px -2px 4px rgba(255, 255, 255, .7); } 50% { text-shadow: 20px 20px 50px rgba(255, 255, 255, .5), -20px -20px 50px rgba(255, 255, 255, .5); } }

However, unlike mix-blend-mode , not all the same properties can be animated. For example, text-indent won’t work here and neither will transform . It’s true that CSS transforms can be applied to SVG elements but because our mask is actually being used as a mask in its truest form, browsers might not apply those transformations.

We can always inject a transform SVG attribute using JavaScript, delivering those transformations to the elements inside the mask:

t = document.querySelector('text'); b = document.querySelector('.backdrop'); b.onmouseover = ()=>{ t.setAttribute('transform', 'translate(20)'); } b.onmouseout = ()=>{ t.removeAttribute('transform'); }

Conclusion

When it comes to browser support and production safe code, CSS mask lags behind due to being limited to Firefox support. The blend modes mentioned in this post are supported in almost all the major browsers, except Edge. The background-clip property is also supported by all the browsers, but still requires -webkit prefix.

In terms of result, both blend modes and mask give similar output. Between background-clip and mix-blend-mode values, it’ll be the choice of the design that’ll lead to choosing one over another. What you can achieve with background-clip can also be done by blending, provided you’re using either only black or white background matching the page’s body.