Animating Link Underlines

Hover this text

I recently added a simple visual effect to this blog that I quickly fell in love with: when you hover blog headers, the link’s underline is revealed by animating it out from the center. You can try it in the banner above. Creating this effect is surprisingly easy, and doesn’t require any additional DOM elements to be added through HTML.

The first thing we need to do is set text-decoration to none for the link, and set the its position to relative so that we can position our border element relative to it. For simplicitiy’s sake, we’ll also make sure the link doesn’t change color on hover:

a {
  position: relative;
  color: #000;
  text-decoration: none;
}

a:hover {
  color: #000;
}

Next we want to add the border and hide it through a transformation. We can do this by utilizing the ::before pseudo-element and setting its X scale to 0:

a::before {
  content: "";
  position: absolute;
  display: block;
  width: 100%;
  height: 2px;
  bottom: 0;
  left: 0;
  background-color: #000;
  transform: scaleX(0);
  transition: transform 0.3s ease;
}

At the very bottom we tell the element to animate transform changes with a duration of 0.3 seconds. For the line to appear, now we just need to make the element visible again on hover by set its X scale back to 1:

a:hover::before {
  transform: scaleX(1);
}

With that, we’ve got an underline that expands on hover:

Hover this text

Here’s all the code, taken together:

a {
  position: relative;
  color: #000;
  text-decoration: none;
}

a:hover {
  color: #000;
}

a::before {
  content: "";
  position: absolute;
  display: block;
  width: 100%;
  height: 2px;
  bottom: 0;
  left: 0;
  background-color: #000;
  transform: scaleX(0);
  transition: transform 0.3s ease;
}

a:hover::before {
  transform: scaleX(1);
}

Changing the direction of the line animation

We can change the direction of the animation by adjusting the line’s transform-origin property. The transform-origin represents the origin of an element’s transformations. It’s set to the middle of an object by default, causing the element to scale from its center point in this instance. To animate it from the left, we can set the origin point to the far left (transform-origin: top left), and to animate it from the right, we can set it to the far left (transform-origin: top right):

Hover me (from left) Hover me (from right)

To change the direction, declare the transform-origin on the ::before pseudo-element of the a element, like so:

/* Animate the line from the left */
a::before {
  content: "";
  position: absolute;
  display: block;
  width: 100%;
  height: 2px;
  bottom: 0;
  left: 0;
  background-color: #000;
  transform: scaleX(0);
  transform-origin: top left;
  transition: transform 0.3s ease;
}

/* Animate the line from the right */
a::before {
  content: "";
  position: absolute;
  display: block;
  width: 100%;
  height: 2px;
  bottom: 0;
  left: 0;
  background-color: #000;
  transform: scaleX(0);
  transform-origin: top right;
  transition: transform 0.3s ease;
}