One benefit of building my personal website from scratch instead of using a theme made by someone else is that I can start from the browser’s defaults and gradually add my own flourishes. I strive to keep my site lean, but making it personal is also kind of the point. There is a spectrum of gratuitous touches between the spartan pages of Hacker News and Craigslist on one end and the sensory overload of old MySpace on the other.
Here’s what the effect looks like now.
The topic of drawing lines under text on the web can be surprisingly complicated, depending on how far you are willing to stray from
text-decoration: underline and which details (like clearing descenders) you care about.
I investigated a few approaches:
Both of them essentially remove the default text-decoration and add a simulated border using pseudo-elements. The border is then animated by CSS transitions. Unfortunately, these solutions have one drawback: they don’t work properly if the link spans more than one line. The underline only appears on the first line.
Here is the relevant code. You can use this repl to play around with it.
Let’s go through this approach part by part. First, we turn off the default
text-decoration for links.
We want to use background-image because it can span multiple lines. While we could supply an actual image, we only want to draw a line, so we use linear-gradient, which generates an image for us. Normally, it’s used to create a gradient between two different colors, but I want the underline to just be the same color as the link, so I use currentColor for both the beginning and the end of the gradient.
currentColor tells the browser to use the element’s computed color property.
We use background-position to place the image in the bottom left corner.
0% sets the horizontal position, and
100% sets the vertical position.
We turn off background-repeat to prevent it from creating multiple instances of the image to fill the entire background of the link.
We use background-size to make the image zero pixels wide and two pixels tall. It has zero width because the underline should only appear on hover.
We set a transition on
background-size, so any change to the property will take
0.3 seconds to complete.
On link hover, we change the width of the image to
100%, creating a full underline, and
transition takes care of the animation. As nickels55 suggests, we also want the effect to happen on focus for those who use keyboard navigation. Thanks to nickels55 for keeping accessibility in mind.
And that’s it! I was very happy with how small the commit ended up being. If you’d like to add something similar to your site, feel free to take this implementation, or check out some other animated underline effects for inspiration.