Underline Animation With CSS Only

What are we going to rebuild

In this Blog Post from my UI / UX Bits series, we will rebuild a nice hover interaction built by https://www.discoveroutpost.com/.

We going to rebuild this UI interaction.

What do we see?

We see a hover effect on an element, where as soon as the mouse is on the element an underline grows from left to right. When the mouse leaves the element, the underline shrinks from left to right.

If you want to go straight to the code, you can play with it here.

How can we recreate it?

Here is our very simple and basic HTML, we just have a link with the class "underline-hover", that's it.

<!DOCTYPE html>
<html lang="en">
    <title>Hover Underline Effect With CSS Only</title>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link href="style.css" rel="stylesheet" />
    <a class="underline-hover" href="/">karimould.dev</a>

First, we start by styling the link with the following CSS:

.underline-hover { 
    text-decoration: none; 
    font-size: 2rem; 
    color: black; 
    font-weight: bold;
    text-transform: uppercase; 
    position: relative; 

This code sets the text-decoration to none, which removes any default underlining from the link. We also set the font size, color, font weight, and the text-transformation to give the link our desired look.

We set the position to relative, to allow our underline to be positioned absolutely under our link later.

Next, we create the underline effect using ::after to create a pseudo-element:

.underline-hover::after {
  content: "";
  position: absolute;
  height: 2px;
  background-color: black;
  left: 0;
  bottom: 0;
  width: 100%;
  transition: transform 0.75s;
  transform-origin: bottom right;
  transform: scaleX(0);

The content property is used to specify the content of a pseudo-element. In this case, the pseudo-element is ::after, which is used to add content after the main content of an element.

You can read more about the ::after property here.

The content property is set to an empty string, which means that no content is added after the main content of the link. We set an empty string as content to add a only styleable pseudo-element to our link element for our underline.

The pseudo-element is positioned absolutely at the bottom of the link. We set the height, background color, and width to style the underline.

The transition property is used to animate the transform property with a duration of 0.75 seconds.

We use the transform property with the scaleX function to hide the underline initially.

The scaleX() function in CSS is used to scale an element along the x-axis. The x-axis is the horizontal axis, so scaling along the x-axis will change the width of the element. In this case, the scaleX() function is used with a value of 0, which means that the width of the element will be set to 0. This is used to initially hide the underline, as the underline has a width of 100% and setting the width to 0 will make it invisible.

You can read more about the scaleX function here.

Finally, we create the hover effect by scaling the underline to full width:

.underline-hover:hover::after {
  transform-origin: bottom left;
  transform: scaleX(1);

Since we only want the hover effect on our pseudo-element we need to chain our selectors. The CSS will only apply to our pseudo-element when the link is hovered.

On hover, the transform-origin is changed to the bottom left, and the transform property is set to scaleX(1), which scales the width of the underline to full width. This creates the desired hover effect, where the underline smoothly appears from left to right.

Because the initial transform-origin is set to the bottom right and the scaleX is 0, the underline shrinks from left to right when the mouse leaves the link.


Did you find this article valuable?

Support Karim Ould Mahieddine by becoming a sponsor. Any amount is appreciated!