Skip to main content

Command Palette

Search for a command to run...

Navigation underline animation

Updated
2 min readView as Markdown
N

Front End Developer. I like problem solving and making things pretty. I also like red.

I recently had a design with three tabs and an underline that indicated which was active. I've seen an animation where the line moves between the tabs, but hadn't used it before. So I decided to try it this time. And it turns out to be simple.

For this I've used a navigation rather than tabs, to keep it simple.

The setup

This is just to get the elements in there and centred. Note: it's important that the navigation links are all the same width and have no gap between them.

HTML

<nav>
  <ul>
    <li><a href="#">Home</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">Contact</a></li>
    <li class="line"></li>
  </ul>
</nav>

CSS

nav {
  display: flex;
  justify-content: center;
}

ul {
  display: inline-flex;
  justify-content: center;
  list-style-type: none;
  position: relative;
}

li:not(.line) {
  width: 100px;
}

The line

Our underline here is .line. We're going to absolutely position it below the navigation elements.

.line {
  position: absolute;
  bottom: -8px;
  left: 0;
  width: 33%;
  height: 2px;
  background-color: black;
  transition: left .3s ease;
}

We're transition the left attribute because what we'll do is to move it left based on which link is being hovered/focused.

Since .link is a part of the unordered list, the simplest way to do this is to look at when the lis themselves are being hovered or when their containing link is being focused. This layout is very simple, so it doesn't matter, but on something more interesting it means that the link and the li both have to be the same width and height.

li:first-child:hover ~ .line,
li:first-child:focus-within ~ .line {
  left: 0;
}

li:nth-child(2):hover ~ .line,
li:nth-child(2):focus-within ~ .line {
  left: 33%;
}

li:nth-child(3):hover ~ .line,
li:nth-child(3):focus-within ~ .line {
  left: 67%;
}

And that's all it takes! Although obviously if you were to add a link you'd need to change this to move the left position a quarter of the way across per link. In the design I had the links contained more text and were also set to be the same width. If you need them to be different widths this solution won't work.

The final code

https://codepen.io/editor/nicm42/pen/019f9df5-f58c-7bd6-b0d9-a95385f08756

1 views