A smooth animated navigation menu that slides a highlight indicator from item to item as the user hovers. This technique — sometimes called the "magic line" — gives navigation bars a polished, dynamic feel without requiring Flash or any heavy libraries beyond jQuery.
How It Works
The idea is simple: a thin bar (the indicator) sits beneath the navigation links. When the user hovers over a link, the indicator animates to that link's position and width. When the mouse leaves the nav, the indicator snaps back to the currently active link.
We use jQuery's .position() to find each link's offset within the nav container, .outerWidth() to match the indicator width to the link, and .animate() to smoothly transition between positions.
HTML Structure
<nav id="nav">
<a href="/" class="current">Home</a>
<a href="/about/">About</a>
<a href="/portfolio/">Portfolio</a>
<a href="/kontakty/">Contact</a>
</nav>
CSS
#nav {
position: relative;
display: inline-block;
}
#nav a {
display: inline-block;
padding: 8px 16px;
text-decoration: none;
color: #333;
}
.nav-indicator {
position: absolute;
bottom: 0;
height: 2px;
background: #58a6ff;
}
JavaScript
$(document).ready(function() {
var $nav = $('#nav');
var $indicator = $('<span class="nav-indicator"></span>').appendTo($nav);
var $items = $nav.find('a');
function moveIndicator($el) {
$indicator.stop(true).animate({
left: $el.position().left,
width: $el.outerWidth()
}, 250, 'easeOutQuad');
}
$items.hover(
function() { moveIndicator($(this)); },
function() { moveIndicator($nav.find('a.current')); }
);
moveIndicator($nav.find('a.current'));
});
How to Read the Code
On page load, we create the indicator element dynamically and append it to the nav. We immediately call moveIndicator on the current page's link so the bar starts in the right position.
On hover-in (mouseenter), we call moveIndicator with the hovered element. On hover-out (mouseleave), we pass the .current link so the bar returns to its home position.
The .stop(true) call before .animate() is important — it clears any running animation before starting the new one, preventing the indicator from lagging behind fast mouse movements.
The 'easeOutQuad' easing requires the jQuery Easing Plugin. You can substitute 'swing' for the default jQuery easing if you prefer not to include it.
Customization
- Change the indicator height, color, and position (top instead of bottom) via CSS
- Adjust animation speed by changing the
250ms value - Try different easing functions for different feels —
easeInOutCubicis another good option - Add a border-radius to the indicator for a pill shape