# My take on fading content using transparent gradients in CSS

Two days ago Amit Merchant wrote a blog post on [a technique to fade text out](https://www.amitmerchant.com/fading-content-using-transparent-gradients-in-css/) using an overlaid element based on the design of [Trunk.io](https://trunk.io). He walks through how he came to this solution so go check out the article to see how it's built. Here's the end result:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec non pharetra lorem, ac feugiat nunc. Maecenas ac aliquet turpis. Pellentesque interdum turpis tortor, ac rhoncus nisi egestas et. Sed in ante diam. Proin ac vehicula velit. Ut fringilla mauris quis lobortis efficitur.

The effect looks great but it has two downsides:

*   The text behind the gradient is no longer selectable
*   The effect only works on solid background colors.

Both of these are also present in the Trunk.io design that Amit based this on. The first issue is easy to fix: you add this to your overlaid element:

```css
user-select: none;
```

That will prevent the overlaid element from capturing mouse events, so you can select words behind the gradient as well.

The second downside requires a different approach if we want the same effect to work with a non-solid background like an image or gradient. To make it work there, we need to **actually make the text fade**, rather than make it look like it fades.

Modern CSS gives us not one, but two different approaches to achieve this. They have a slightly different result, so we'll go over each one and discuss their differences.

For both approaches, we're going to use the same HTML structure:

```html
<p>
  <span> Lorem ipsum dolor sit amet consectetur [...] </span>
</p>
```

For this to work, we need an additional wrapper element around the text. In this case we're using a `p` and `span`, but if you already have a different container element around your `p` you could use that instead.

To make the effect easy to see, we'll give our `p` some default styling and add a gaudy background gradient:

```css
p {
  background: linear-gradient(to right, blue, red);

  max-width:30rem;
  padding: 20px;
  border-radius: 20px;

  font-family: system-ui;
  font-weight: bold;
  color: white;
}
```

The end result looks like this:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec non pharetra lorem, ac feugiat nunc. Maecenas ac aliquet turpis. Pellentesque interdum turpis tortor, ac rhoncus nisi egestas et. Sed in ante diam. Proin ac vehicula velit. Ut fringilla mauris quis lobortis efficitur.

With that as our backdrop, let's look at the two different ways to achieve faded content: `background-clip` and `mask-image`.

## Technique one: background-clip

The `background-clip` CSS property lets you define where your background should be restricted to: the entire element (`border-box`, which is the default), inside the border with `padding-box` or sit only behind the content with `content-box`.

But background-clip has a fourth value of `text`. Setting this will restrict the background to be visible only behind the text.

Just doing that doesn't _actually_ change the way it looks, because the text also has a color that overlays the background. When using `background-clip: text` you want to combine it with `color: transparent`.

Lastly to make that text fade, we're going to set the background to a linear gradient that fades from our text color (white) to transparent.

Combined, this is what that looks like:

```css
span {
  display: block;
  background: linear-gradient(to bottom, white, transparent);
  color: transparent;
  background-clip: text;
}
```

And here is the result:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec non pharetra lorem, ac feugiat nunc. Maecenas ac aliquet turpis. Pellentesque interdum turpis tortor, ac rhoncus nisi egestas et. Sed in ante diam. Proin ac vehicula velit. Ut fringilla mauris quis lobortis efficitur.

Notice how the text fades into the background evenly across the gradient, and how each word remains selectable because we're not overlaying anything on top of the text.

[

### Polypane has everything you need to build great sites

Learn about Polypane](/)

### Browser support

`background-clip: text` is supported in all evergreen browsers and has been for quite a while (support in all evergreen browsers since 2016 when it landed in Firefox) so it's save to use.

Until fairly recently, Safari (2020) and Chromium (December 2023) required you to use `-webkit-background-clip` so for backwards compatibility you will probably also include the prefixed version:

```css
span {
  display: block;
  background: linear-gradient(to bottom, white, transparent);
  color: transparent;
  -webkit-background-clip: text;
  background-clip: text;
}
```

Make sure to put the prefixed version _before_ the standard declaration. In CSS the last declaration wins, so the standard will overwrite the prefixed version and be used instead

### Downsides

This technique works well, but it has a downside. Because the text is now transparent, it takes on the color of the background. If your content had different colors for elements like links or other elements like emoji, those colors are either replaced or they don't fade:

Emojis: 😬🫣😱🚀✨Lorem ipsum dolor sit amet, consectetur adipiscing elit.  
Lorem [My hotpink link](#) ipsum dolor sit amet, consectetur

If you want to keep those as well as fade the content out, we need a different technique.

## Technique two: mask-image

`mask-image` lets you use an image (or SVG or gradient) as a mask layer, similar to how that works in graphics editors.

Usually the alpha channel of the mask image is used to determine which parts of your element are visible and which ones aren't, but you can set `mask-mode` to `luminance` and use a black-white mask instead. For our purpose though, the alpha channel is fine.

Here's what the CSS looks like for that:

```css
span {
  display: block;
  mask-image: linear-gradient(to bottom, white, transparent);
}
```

As well as the rendered result:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec non pharetra lorem, ac feugiat nunc. Maecenas ac aliquet turpis. Pellentesque interdum turpis tortor, ac rhoncus nisi egestas et. Sed in ante diam. Proin ac vehicula velit. Ut fringilla mauris quis lobortis efficitur.

Like the `background-clip` technique the words are still individually selectable, and text fades into the background evenly across the gradient. Because this is a mask across your element however, the specific colors of your text are preserved.

Emojis: 😬🫣😱🚀✨Lorem ipsum dolor sit amet, consectetur adipiscing elit.  
Lorem [My hotpink link](#) ipsum dolor sit amet, consectetur adipiscing elit. Donec non pharetra lorem

### Browser support

`mask-image` has been supported across evergreen browsers since 2017, so a little less than `background-clip`. The earlier mentioned `mask-mode` has only been available since December 2023 when support landed in Chromium (both Safari and Firefox had support for it since 2022 and 2017 respectively). Currently for Edge support you still need to include the prefixed `-webkit-` version:

```css
span {
  display: block;
  -webkit-mask-image: linear-gradient(to bottom, white, transparent);
  mask-image: linear-gradient(to bottom, white, transparent);
}
```

I'm not sure why Edge specifically has this, as it's running the same version of Chromium as Chrome and Polypane, which don't need it. So that's a little complication you have to be aware of.

### Downsides

The main downside of `mask-image` is that it also masks the selection style of your text. When selecting the text with the `background-clip` technique it becomes clearly readable because the selection undoes the background clip. With `mask-image` the selection is also faded, which makes the text harder to read.

The browser support for the unprefixed version is relatively new, so for backwards compatibility you also need the prefixed properties. It's a little more flexible than `background-clip` because it doesn't change the color of your text, though that might be a downside if you _do_ want to change the color of your text.

## Fading text content

So that's two ways to fade text content. `mask-image` is a little more flexible, but `background-clip` is a little more widely supported. Both are great ways to fade text content, and I hope you can use them in your projects!

---

Polypane is the browser built for developers and designers — try it at https://polypane.app.
