I just recently had to make animated underlines for links in a menu and came across some code that used backgrounds to create the effect. It's a pure CSS effect and uses various properties of the background property such as background-size
, background-image
, and then it uses a transition. In a nutshell, it makes use of layered background images and makes them 2px high, positioned at the bottom. You then use a transition and animate the top layer to cover 100% on hover. Below is the code to achieve the effect.
a {
color: #1c5ffe;
background-image: linear-gradient(90deg, rgb(10, 60, 61) 10%, rgb(45, 104, 253) 50%), linear-gradient(90deg, rgb(56, 110, 143) 10%, rgb(8, 213, 189) 50%);
background-position: 0 100%;
background-size: 0 2px, 100% 2px;
background-repeat: no-repeat;
transition: background-size 2s;
}
a.gradient:hover {
background-image: linear-gradient(90deg, rgba(34, 193, 195, 1) 10%, rgb(45, 104, 253) 50%), linear-gradient(90deg, rgb(56, 110, 143) 10%, rgb(8, 213, 189) 50%);
background-size: 100% 2px, 100% 2px;
background-repeat: no-repeat;
cursor: pointer;
}
If you want more details you can find them here. https://nickymeuleman.netlify.app/blog/css-animated-wrapping-underline
The site I was working on also had a nice animated effect on links that used a span and pseudo-classes but it came to our notice that even though the effect was nice it relied on the element being a block element. That meant on smaller screen sizes or narrower containers the text didn't wrap nicely with longer links. So I decided to try the idea above and work from my article on gradient text backgrounds to see if I could make a similar effect that wrapped and to my delight I was successful. Below you can see that it wraps nicely.
You can use the resize handle to see how the links wrap nicely. Please also note, that so you can see the effect I have used a 2-second transition. A transition timing of 200-300ms is possibly better in most circumstances.
How to make animated gradient text backgrounds
Follow the step below to create this wonderful effect.
-
The first thing we are going to need is an extra span inside the <a>. This could be a game stopper for some but if you really want to use it on all links you could add this dynamically using a small piece of JavaScript. I will also note here that I tried to use a pseudo before class and this didn't work, unfortunately.
<a class="gradient"><span>Serif Fonts are Nice</span></a>
-
First, let's deal with the span and add a nice gradient background to it. We also need to add the top gradient and make it 0 in size. The
a > span
CSS rule will now look like this.a > span { background: linear-gradient(90deg, rgb(56, 110, 143), rgb(45, 104, 253)), linear-gradient(90deg, rgb(56, 110, 143), rgb(8, 213, 189)); background-size: 0 100%, 100% 100%; background-repeat: no-repeat; color: rgb(8, 213, 189); }
Note that the first background value in the background properties in the comma-separated list is the top, this is different from HTML where the following elements are on top.
Also, I am addingno-repeat
for background-repeat. Background repeat is needed to stop the un-hover "jolt" to starting colour. -
Next, we need to add a transition to the rule. You can specify all or add separate properties.
background-repeat: no-repeat; color: rgb(8, 213, 189); + transition: all 2s; }
-
Now add a hover rule to the span. All we need to do is adjust the size of the top background to be 100% and we are done, we have a nice gradient background animating.
a > span:hover { background: linear-gradient(90deg, rgb(56, 110, 143), rgb(45, 104, 253)), linear-gradient(90deg, rgb(56, 110, 143) 10%, rgb(8, 213, 189)); background-size: 100% 100%, 100% 100%; background-repeat: no-repeat; /* Need this on the hover state so you get the effect of it growing from left to right */ }
-
Finally, add the text clip property to both the
a > span
anda > span:hover rules
. If you want more information on using background-clip and some ideas about how it works I wrote a detailed article on that so you can get your gradient backgrounds just right, especially when using with headings that are block elements.+background-clip: text; +-webkit-background-clip: text; +-webkit-text-fill-color: transparent;
That's if you now have a nice hover effect on your text links. Just add the underline from above. You can either make it animate in or if you are using it in paragraph text use the same background rules and make the gradient animate.
Here is the final code.
a.gradient {
color: #1c5ffe;
background-image: linear-gradient(90deg, rgb(10, 60, 61) 10%, rgb(45, 104, 253) 50%), linear-gradient(90deg, rgb(56, 110, 143) 10%, rgb(8, 213, 189) 50%);
background-position: 0 100%;
background-size: 0 2px, 100% 2px;
background-repeat: no-repeat;
transition: background-size 2s;
}
a.gradient:hover {
background-image: linear-gradient(90deg, rgba(34, 193, 195, 1) 10%, rgb(45, 104, 253) 50%), linear-gradient(90deg, rgb(56, 110, 143) 10%, rgb(8, 213, 189) 50%);
background-size: 100% 2px, 100% 2px;
background-repeat: no-repeat;
cursor: pointer;
}
a.gradient > span {
background: linear-gradient(90deg, rgb(56, 110, 143), rgb(45, 104, 253)), linear-gradient(90deg, rgb(56, 110, 143), rgb(8, 213, 189));
background-size: 0 100%, 100% 100%;
background-repeat: no-repeat;
color: rgb(8, 213, 189);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
transition: all 2s;
}
a.gradient > span:hover {
background: linear-gradient(90deg, rgb(56, 110, 143), rgb(45, 104, 253)), linear-gradient(90deg, rgb(56, 110, 143) 10%, rgb(8, 213, 189));
background-size: 100% 100%, 100% 100%;
background-repeat: no-repeat;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
Nice work! Now we can beautiful CSS links everywhere we want!
If you liked this short snippet be sure to sign up for my newsletter. I write about front-end development and also Drupal, which is the engine behind this site. Thanks for reading and see you next time.