UI Challenge: Sliding Highlighter
Make a sliding highlighter for hovered navigation
In this article
Specifications
We’re creating a visual indicator that will follow the currently hovered navigation item. This highlighter will:
- Appear directly behind the hovered element.
- Move to a new position when a different element is hovered.
- Change its width to match the width of the element it’s highlighting.
We can see a demo we’re creating here. To interact with this demo, you’ll need to use a pointing device like a mouse. If you’re on a device that doesn’t have a mouse, you can watch a video demonstration instead.
Video
Basic Idea
The core idea is to add an element that acts as a highlighter and then transition the values of its opacity
, transform
, and width
properties. Here’s a breakdown:
- Initially, the highlighter’s
opacity
is set to0
. When hovered over, itsopacity
changes to1
. - Apply
position: absolute;
to the highlighter. - Position it relative to its container using
transform: translateX(x);
. The value ofx
is theoffsetLeft
of the currently hovered element. - Set the
width
based on theoffsetWidth
of the currently hovered element.
Step 1: Basic Markup and Styling
This is the fundamental HTML structure and CSS.
Step 2: Add a mouseover
Listener
To make the highlighter follow the mouse, we’ll attach a listener to each menu item. When a user hovers over an item, we’ll calculate the exact position
and width
of the item and then apply these values to the highlighter. The position will be set via transform: translateX(...)
where the value is set to the offsetLeft
of the hovered menu item. And the width is set to match the offsetWidth
of the hovered menu item via width
property. These will create a dynamic effect that visually indicates which menu item is currently being hovered over.
Step 3: Handle the Initial Hover
So far, we’ve met specifications 2 and 3. However, when we hover outside the navigation and then back onto an item, the highlighter might not behave as expected. Notice that the highlighter appears at the previously hovered element before moving to the new one. This behavior doesn’t align with specification 1. To fix this, we need to differentiate behavior between the first hover and subsequent hovers:
- Add a variable
entered
to track the hover state with the default value offalse
to indicate that no element has been hovered over yet. - Upon the first hover over a navigation item, only transition the
opacity
property and setentered
totrue
. - For subsequent hovers, transition the
opacity
,transform
, andwidth
properties. - When the hover leaves the navigation element (i.e.
.nav
) element, setentered
back tofalse
.