What & Why
This technique creates a smooth animated highlight bar that moves between navigation links using CSS transforms and transitions. Traditionally, navigation hover effects were built by changing background colors on each link, which often felt abrupt and visually inconsistent. By animating a single highlight element instead, we achieve smoother motion, better performance, and a more polished user experience.
How It Works
The highlight is a separate <span> element positioned absolutely within the nav container.
When hovering over a link, JavaScript calculates the link's width and position, then animates the highlight
to match using CSS transforms. This creates a fluid sliding effect.
Code Snippet
/* CSS Transition */
.highlight {
transition: left 0.4s cubic-bezier(.4,0,.2,1),
width 0.4s cubic-bezier(.4,0,.2,1);
}
/* JavaScript Logic - FIXED */
link.addEventListener("mouseenter", () => {
const linkRect = link.getBoundingClientRect();
const navRect = nav.getBoundingClientRect();
const leftPosition = linkRect.left - navRect.left;
highlight.style.width = `${linkRect.width}px`;
highlight.style.left = `${leftPosition}px`;
});
/* Mobile - Hide highlight */
@media (max-width: 767px) {
.highlight {
display: none;
}
}
Key Benefits
- Smooth Performance: Uses GPU-accelerated transforms
- Accessible: Maintains keyboard navigation
- Responsive: Adapts to different screen sizes
- Customizable: Easy to change colors and timing
Live Demo
Hover over the navigation links above to see the highlight animation in action. The highlight smoothly follows your cursor and resizes to match each link. On mobile, the highlight is automatically hidden since hover states don't exist on touch devices.
Gotchas & Considerations
- The highlight requires JavaScript to dynamically follow the hovered link. Without JS, it stays static on the active link.
- If you add or remove links dynamically, you need to re-initialize the highlight widths and positions.
- Make sure the nav container has
position: relativeand the highlight hasposition: absolute. - Mobile: Always hide hover effects on mobile using media queries - hover states don't exist on touch devices.
Resource
Inspired by Smashing Magazine: Creating a Moving Highlight Navigation Bar with JavaScript and CSS