Create a Gradient Underline with Tailwind CSS

March 22nd, 2023

Today we're going to look at how to create a gradient underline with Tailwind CSS. We're also going to explain the CSS at every step to make sure you understand exactly what each class is achieving. Here's what you'll be able to recreate with Tailwind after following this article:

example of a gradient underline with tailwind

Setup

Let's start with some simple markup for our effect:

<p>Hello <span>Friend</span></p>

Let's add some simple base styles for the text too:

<p class="text-2xl font-semibold font-sans">Hello <span>Friend</span></p>

Here's what we should have to start off with:

Hello friend starter text

Background Gradient

You might be tempted to reach for the underline class in Tailwind to create this effect. However, this will use the CSS text-decoration: underline; under the hood and you can't color a native underline with a gradient using the text-decoration-color property.

So how do we work around this? We'll create a gradient background and make the background only appear at the bottom of the text… Let's go ahead and apply the gradient background:

<p class="text-2xl font-semibold font-sans">
  Hello
  <span class="bg-gradient-to-r from-green-300 via-blue-500 to-purple-600">
    Friend
  </span>
</p>

All we've done here is apply a few Tailwind classes to the span element to give the "Friend" text the gradient background. Feel free to checkout Tailwind's documentation on gradients.

If you're curious, I got that gradient from hypercolor.dev. That site has some nice pre-made gradients you can pick from, or options to generate your own unique gradient.

After applying that gradient background, we should have something like this:

Text with gradient background

Resizing the Gradient

By default, the background gradient will fill up all the space of the span element. But we only need the gradient to be a few pixels tall. We can achieve this by adding the following two classes:

  1. bg-[length:100%_5px]
  2. bg-no-repeat

Let's look at the results of these two additional classes, and then we'll break down what they're doing:

<p class="text-2xl font-semibold font-sans">
  Hello
  <span
    class="bg-gradient-to-r from-green-300 via-blue-500 to-purple-600 bg-[length:100%_5px] bg-no-repeat"
  >
    Friend
  </span>
</p>
Text with gradient background at top

In order to specify an explicit size we want for this background, we could use the CSS property background-size. In plain 'ole CSS, if you provide two values to this property, it will use the first value as the width of the background and the latter as the height.

Text with gradient background

In this example, if we set background-size: 100% 100px; , the image will stretch to fill the full width of the parent container and the height of the background image will be 100px. This will make the background image look distorted as the aspect ratio of the original image is not maintained. You'll also notice that because the background image does not fill the full height of the parent container, the image is repeated by default. This is why we use the bg-no-repeat class - to prevent the gradient from being repeated and filling the height of the span.

But what about this bg-[length:100%_5px] class? This is how we set the background-size property in Tailwind. Everything inside the square brackets is an arbitrary value. An arbitrary value can be used in Tailwind when you want to use a specific value that is not within the constraints of Tailwind's design system.

Tailwind's documentation explains this well:

"When you find yourself really needing something like top: 117px to get a background image in just the right spot, use Tailwind's square bracket notation to generate a class on the fly with any arbitrary value: <div class="top-[117px]">"

If the arbitrary value you are trying to use requires a space, you can use an underscore instead and Tailwind will replace it with a space at build time. That explains the 100%_5px.

Sometimes when using arbitrary values, there is some ambiguity that needs to be clarified. For example, Tailwind allows you to write both text-lg and text-black classes. So if you use an arbitrary value with the text scope, like text-[var(--my-var)], it's not clear if you are trying to set the font-size or the font-color. For this reason, Tailwind lets you prefix your arbitrary value with a CSS data type. This is exactly what we are doing with length:100%_5px. We are tipping off Tailwind to the fact that we are using a length data type so it can infer that we are trying to set the background-size property.

Positioning the Gradient

The last thing we need to do is move our background image to the bottom of the span! This is exactly what the background-position property is used for! In Tailwind we simply add the class bg-bottom which is equivalent to background-position: bottom;.

<p class="text-2xl font-semibold font-sans">
  Hello
  <span
    class="bg-gradient-to-r from-green-300 via-blue-500 to-purple-600 bg-[length:100%_5px] bg-no-repeat bg-bottom"
  >
    Friend
  </span>
</p>

And with that last class, we have an awesome gradient underline 😃. If you would like to see my version, feel free to checkout my codepen. I also added a little bit of padding to the bottom of the span to give a small amount of space between the bottom of the text and the background image.

example of a gradient underline with tailwind