AI CSS Animations

Guides · · Maxwell Prehoda

12 Navbar Hover Effects From Real Sites and CSS Classics, With Live Demos

The best navbar hover effects do one job: they show which item you are about to pick, and they get out of the way. In practice that means one of four patterns: an underline that draws in, an indicator that slides between items, a dropdown that morphs to fit its content, or a playful effect for sites where personality matters more than speed. Below are 12 examples of those patterns from CSS-Tricks, Codrops, Stripe, Radix and others, plus three of our own pure-CSS versions you can play with right on the page.

Each entry says what it is best for, what it runs on and what will bite you. We opened every source linked here, and where a live demo sits under a third-party entry, it is our pure-CSS take on the pattern, not that author's code.

1. Hover.css underline and overline transitions by Ian Lunn: Best for a classic underline on a marketing site top nav

Platform: CSS, Sass or LESS; MIT for personal use, paid commercial license

Live from our directory: Underline from Center Link. Copy the HTML and CSS →

Hover.css is one of the oldest and best-known hover libraries on the web. Its Border Transitions group holds the effects most navbars need: Underline From Left, Underline From Center, Underline From Right, Underline Reveal, and the matching Overline variants.

What makes the pattern work is restraint. A 2px line that grows from the centre tells the user exactly where the pointer is without moving any text, so the menu never feels jumpy.

Our Underline from Center Link below is a pure-CSS version of the same idea: a pseudo-element scaled on X, which is cheaper than animating width.

Watch out for: Commercial projects need a paid Hover.css license (the free MIT terms exclude selling the application). Also add a :focus-visible rule that shows the same line, because hover-only underlines leave keyboard users guessing.

Hover.css on GitHub ↗

2. Inspiration for Line Menu Styles on Codrops: Best for picking a line style before you write any code

Platform: HTML + CSS demos, free on Codrops

Manoela Ilic (Mary Lou) published this open collection on Codrops in January 2016: a set of menus where a single line is the whole design. The line sits absolutely at the bottom of each link, scaled to zero on the X axis, and grows to full width on hover or when the item becomes current. The variations come from where the line starts, how thick it is and how it leaves.

It is still the fastest way to see a dozen line treatments side by side and decide which one fits your brand.

Watch out for: The code dates from 2016, before :focus-visible was widely supported, so check each style's keyboard focus state and add one where it is missing.

More Codrops link demos ↗

3. Magic Line navigation by Chris Coyier (CSS-Tricks): Best for an indicator that returns to the current page

Platform: jQuery + CSS (2010 tutorial)

Live from our directory: Gliding Underline Nav Hover Effect. Copy the HTML and CSS →

This is the article that made the sliding indicator famous. A highlight, either an underline or a background, follows the pointer across the menu and slides back to the current page's item when the pointer leaves. The script stores the current item's width and position on load, then animates the line to each hovered link's position.

The part worth copying is the return: an indicator that rests under the current page doubles as a "you are here" marker.

Our Gliding Underline below does the same glide and return in pure CSS: :has() sets an offset variable for whichever item is hovered, and a slower faint echo trails the main line.

Watch out for: The original depends on jQuery and measures the DOM on load, so it drifts if fonts load late or the nav resizes. Today :has() or anchor positioning can do it without a script.

4. Our Directional Underline nav: Best for text navs where the line should follow the pointer

Platform: Motions directory, free, pure CSS Ours

Live from our directory: Directional Underline Nav Hover Effect. Copy the HTML and CSS →

Move along this menu and the old underline retracts toward the item you are heading to while the new one grows from that side. Each item owns its own pseudo-element, so there is no measuring and no JavaScript.

The trick is a sibling selector that flips transform-origin for items after the hovered one, plus a transition on transform-origin that waits 0.3s so the line does not snap direction mid-animation. It works on :focus-visible as well as :hover, and the current page keeps its accent colour.

Watch out for: The direction logic assumes a single row. If your nav wraps onto two lines on tablets, the line will grow from the wrong side on the second row.

5. Vercel-style hover highlight with Motion layoutId: Best for React and Next.js apps with a tabbed top nav

Platform: React + Motion (formerly Framer Motion) + Tailwind

Live from our directory: Sliding Pill Nav Hover Effect. Copy the HTML and CSS →

Vercel's dashboard popularised a background pill that follows the pointer across tabs. Ashirvad Bhushan's tutorial rebuilds it in Next.js: a motion.div with a shared layoutId renders only behind the hovered link, and Motion animates it from one link to the next with a spring. As he puts it, each link's background "would follow the cursor on hover over the navbar."

Shared layout animation suits tabs of changing width, because Motion measures the real boxes for you.

If you would rather not ship a JavaScript animation library for this, our Sliding Pill nav below is a pure-CSS version for fixed menus: :has() moves one pill to the hovered item and back to the current page.

Watch out for: The tutorial tracks onMouseOver and onMouseLeave only, so keyboard users get no highlight until you add onFocus and onBlur. Keep the spring bounce low; a wobbling pill on every hover gets tiring fast.

Motion layout animations ↗

6. Anchor positioning tab underline (Chrome for Developers): Best for zero-JavaScript indicators on modern browsers

Platform: Pure CSS, anchor positioning (Baseline 2026)

CSS anchor positioning lets one element position itself against another, which is exactly what a sliding indicator needs. Chrome's guide gives the active list item anchor-name: --active, then tethers a ::before on the list to it with position-anchor and anchor() insets. A transition on inset makes the line slide when the active item changes.

Temani Afif took the idea further on CSS Tip with two menu hover experiments, one sliding and one jumping, where the anchor follows the hovered item. Per MDN's compatibility data, anchor-name ships in Chrome and Edge 125, Firefox 147 and Safari 26, and MDN lists anchor positioning as Baseline newly available since January 2026.

Watch out for: Do not use position-area for the indicator: the guide notes it cannot be transitioned. Wrap the transition in a prefers-reduced-motion: no-preference query, pair the line with aria-current, and keep a static border fallback behind @supports for older browsers.

7. Stripe's morphing dropdown, rebuilt by Lokesh Dhakar and CodyHouse: Best for SaaS mega menus with panels of different sizes

Platform: CSS transforms + a little JavaScript

Stripe's main navigation is the reference everyone copies: instead of swapping separate dropdowns, one white panel morphs from the size of one menu to the next. Lokesh Dhakar's tutorial explains how: the background box moves with translateX and resizes with scaleX and scaleY, the content lives in a separate sibling so it never stretches, the sections cross-fade on opacity, and the popover swings open from rotateX(-15deg). His timings are 0.4s for the morph and 0.3s for the swing.

The reason it uses transforms is performance. Animating width, height or left makes the browser recalculate layout every frame; his DevTools audit of the transform version found "Zero work on the main thread." CodyHouse's version does the same with a 1px background layer scaled to each panel's pixel size.

Watch out for: Scaling a box also scales its border-radius and shadow, which is why these builds keep the panel's corners and arrow on separate layers. Both write-ups describe Stripe's navigation at the time they were written; the live stripe.com nav may have changed since.

CodyHouse Stripe navigation ↗

8. Radix UI Navigation Menu: Best for accessible dropdown navs in a React design system

Platform: React, Radix Primitives (free, unstyled)

Radix gives you the hard parts of a dropdown nav with the motion left to you. The Content part carries a data-motion attribute (from-start, from-end, to-start or to-end), so you can slide panels in from the side the pointer came from. The Viewport exposes --radix-navigation-menu-viewport-width and --radix-navigation-menu-viewport-height, which is how you get a Stripe-style morph between panel sizes, and the Indicator exposes a translate variable for a sliding arrow or underline.

The real win is keyboard support: Enter and Space open a trigger, arrow keys move between triggers and into the content, Home and End jump, and Esc closes and returns focus. Root defaults delayDuration to 200 and skipDelayDuration to 300.

Watch out for: It ships unstyled, so every keyframe for each data-motion value is yours to write. Test the direction-aware slides with reduced motion turned on and swap them for a short fade.

9. Our Dropdown Menu on Hover: Best for simple sites that need one dropdown and no framework

Platform: Motions directory, free, pure CSS Ours

Live from our directory: Dropdown Menu on Hover. Copy the HTML and CSS →

A Products button that unfolds a small panel on hover or keyboard focus, with each item dropping in a beat after the last. The chevron turns as the panel opens, and an invisible hover bridge between trigger and panel stops the menu closing while the pointer crosses the gap, which is the most common bug in hand-rolled hover menus.

Pick it for a marketing site with one or two dropdowns, where a component library would be overkill. The reduced-motion rule skips the transition but keeps the menu working.

Watch out for: Pure-CSS hover menus cannot close on Esc or move focus with arrow keys. If your nav has several dropdowns or nested levels, use a component like Radix instead.

10. Gooey menu by Lucas Bebber (CSS-Tricks): Best for playful sites, games and creative portfolios

Platform: CSS + inline SVG filter

Lucas Bebber's 2015 guest post on CSS-Tricks opens with a menu whose items blob out of the trigger and stick together like liquid. The effect is an SVG filter applied with CSS: feGaussianBlur blurs the shapes, then feColorMatrix sharpens only the alpha channel, so overlapping blurs merge into one smooth shape with crisp edges.

It suits a floating action menu or a portfolio nav that wants to be remembered.

Watch out for: The filter needs a transparent background and some bleed space, and it is expensive on large areas; commenters reported slowdowns on phones. Keep the filtered container small and test on a real mid-range device.

12. Our Menu Hover Effects collection: Best for portfolios and studios that want a nav with a point of view

Platform: Motions directory, free, pure CSS Ours

Live from our directory: Strikethrough Nav Hover Effect. Copy the HTML and CSS →

Our Menu Hover Effects collection gathers every nav, menu and list hover in the directory: sliding pills, gliding and directional underlines, a dot indicator, a skewed fill, swinging tags, a macOS-style dock and more. Each is plain HTML and CSS with a reduced-motion guard and two custom properties for colour and size.

The demo below is the Strikethrough Nav: point at one item and the others get crossed out with a quick slanted stroke, one after another. It is an editorial take on sibling dimming, built with :has() and :not(), which every current major browser supports. For link styles outside the nav, see the Link Hover Effects collection.

Watch out for: Effects that change the other items (strike, blur, dim) only make sense with a handful of items. On a ten-item nav they turn into noise, so save them for short menus.

How to choose a navbar hover effect

Three questions settle it faster than scrolling through another hundred pens.

Match it to the nav

A short text nav of four or five links suits an underline (Hover.css, our Directional Underline) or a sliding indicator (Magic Line, the Vercel-style pill). A nav with dropdowns of different sizes wants a morph (Stripe's) and real keyboard handling (Radix). Playful effects like the gooey menu or strikethrough belong on portfolios, not on a checkout header.

Match it to the stack

On a static site or a CMS theme, stay in CSS: :has() works in every current major browser, and anchor positioning is now Baseline, with a static fallback for older versions. In a React app that already ships Motion, layoutId is the least code for an indicator. If your mobile nav collapses into a hamburger, the hover effect only exists on desktop, so spend the motion budget on the hamburger menu animation as well.

Match it to the moment

Navs get hovered constantly, so keep transitions between about 150 and 300 milliseconds and use ease-out or a gentle spring. Every effect needs a matching :focus-visible state, and the current page should keep its indicator when nothing is hovered. Turn on reduced motion in your OS and check the nav still shows which item is active without the movement. Our post on CSS animations for microinteractions covers the timing side in more depth.

Ship a better nav hover today

Pick the pattern, not the prettiest pen. For a row of text links, copy an underline or indicator demo above and add a current-page marker and a focus state. If it has dropdowns, start from Radix or the Stripe tutorial and keep the motion to a single morph.

If none of these fit your brand, describe your nav to the creator: it asks a few quick questions while it works and returns production-ready CSS you can refine in chat.

A prompt to start from
Make a navbar hover effect for a five-link top nav on a dark SaaS header.
A pill highlight slides to the hovered link in 220ms with a soft spring and returns to the current page (aria-current) when the pointer leaves.
The same highlight appears on :focus-visible for keyboard users.
Pure CSS with :has(), no JavaScript, colour and size as custom properties.
Under prefers-reduced-motion, the pill jumps without sliding.

Make your own with AI →

Common questions

How do I add a hover effect to a navbar in CSS?

Give each link position: relative and add a ::after pseudo-element for the line or background. Set it to transform: scaleX(0) at rest and scaleX(1) on :hover and :focus-visible, with a transition on transform of about 250ms. Scaling a pseudo-element is smoother than animating width, and it does not shift the text.

How do I make a sliding underline that moves between nav links?

There are three routes. Pure CSS with :has() and a custom property works for menus with equal-width items, like our Sliding Pill. CSS anchor positioning tethers one indicator to whichever item is hovered or active, now Baseline across major browsers. In React, Motion's layoutId moves one element between items and handles any widths.

Do navbar hover effects work on mobile?

Not really. Touch screens have no hover, and most mobile navs collapse into a menu button anyway. Make sure the current page is marked without hover, use @media (hover: hover) to scope hover-only flourishes to devices that support them, and put the mobile motion into the menu toggle instead.

Are navbar hover animations bad for accessibility?

They are fine if three things hold: the same state shows on keyboard focus, the current page is marked with aria-current rather than colour alone, and a prefers-reduced-motion rule removes the movement. Avoid effects that blur or move the other links so much that their labels become hard to read.

How long should a nav hover transition be?

Short: 150 to 300 milliseconds with an ease-out curve feels responsive for links people pass over all the time. Longer, bouncier transitions make a product header feel slow.

Sources