In a current project, the designer asked if we could add a little gimmick to the horizontal navigation, which consists of just a few one-level items. Of course the idea is visual-, desktop-, and mouse-input-device-centric, and a discussion about other devices and the resulting state of the navigation ensued, and we agreed to treat this as a nice to have if everything else is cared for.
Nevertheless I was intrigued; would it be possible to animate a border to 'slide' from one menu item to the next on (mouse)over? So if you 'leave' the currently hovered item, the line should follow in that direction and 'enter' the adjactent item accordingly. Leave right, enter left, etc.

Here's what I came up with for a first prototype:

See the Pen Sliding underline by Tom (@webrocker) on CodePen.

Obviously this needs further improvements, but ignoring size and non-mouse input for the moment, I'm pleasantly surprised that this idea is possible. What I wasn't able to solve in this first iteration is the initial transformation. I need to 'detect' if the menu item is 'hovered' from the left or the right side, to trigger the correct direction of the sliding line. Once the mouse is 'over' the item, I'm able to detect the direction of the mouse movement and can set the according classes for the animation, so after the first round of 'wrong' sliding lines, the demo behaves as expected.

Once the initial problem is solved, I'd try to get this to work with touch. And using vanilla JavaScript wouldn't be bad, either.


Here's the second version:

See the Pen Sliding underline v2 by Tom (@webrocker) on CodePen.

The initial state / first transition problem is not resolved, yet. Initially I thought that working only with previous/current indices would be enough, but soon discovered that I need to check for the "direction" of the mouse movement, if a change from left to right or right to left happens on the same menu item. So now I have a slightly more complex JS script, but instead of checking with every mousemove, the position is checked only on mouseleave, while the mouseenter only compares the previous to current index. Which to me seems a bit more performant, even if the end result is not better as in version one. Hm.