webdevpuneet.com

Floating Pill Nav — Free HTML CSS JS Navbar Snippet

Floating Pill Nav · Navigation · Plain HTML, CSS & JS · Live preview

CategoryNavigation

Copy & paste

Source Code

<div class="fp-page">
  <nav class="fp-nav" id="fpNav" aria-label="Primary">
    <a href="#" class="fp-brand">◆ Lumen</a>
    <ul class="fp-links" id="fpLinks">
      <li><a href="#home" class="fp-link active">Home</a></li>
      <li><a href="#features" class="fp-link">Features</a></li>
      <li><a href="#pricing" class="fp-link">Pricing</a></li>
      <li><a href="#docs" class="fp-link">Docs</a></li>
    </ul>
    <a href="#" class="fp-cta">Sign up</a>
  </nav>

  <header class="fp-hero"><h1>Scroll down</h1><p>The pill nav shrinks and lifts as you go.</p></header>
  <section class="fp-fill"></section>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Frosted glass pill
backdrop-filter blur over a translucent rounded bar.
Shrinks on scroll
A single .shrink class morphs width, height, and shadow.
Sliding indicator
A pill follows the hovered and active link via transform.
Passive rAF scroll
Throttled scroll handling keeps the main thread free.
Returns to active
The highlight snaps back when the mouse leaves the list.
Resize-aware
Indicator re-measures on viewport changes.
Responsive collapse
Center links hide below 560px for mobile.
CSS-driven morph
JS only toggles a class; transitions do the animation.

About this UI Snippet

Floating Pill Nav — Shrinking Glass Bar with Sliding Indicator

Screenshot of the Floating Pill Nav snippet rendered live

The floating pill navbar is the navigation style popularized by modern SaaS and product sites: instead of a full-width bar stuck to the top edge, the menu is a rounded "pill" that floats a few pixels below the top, centered, with a frosted-glass background — and it gently condenses as you scroll down. This snippet implements the complete pattern in plain HTML, CSS, and vanilla JavaScript, including a sliding indicator that tracks the active and hovered links.

The floating glass container

The nav is position: fixed and centered with the classic left: 50%; transform: translateX(-50%) trick, then capped at min(720px, calc(100% - 32px)) so it never touches the screen edges. The frosted look comes from a semi-transparent rgba background plus backdrop-filter: blur(10px), which samples and blurs whatever scrolls behind it. A hairline 1px border and a soft drop shadow lift it off the page so it reads as a floating object rather than a docked bar.

Condensing on scroll

A scroll listener — registered as { passive: true } and throttled with requestAnimationFrame so it never blocks the main thread — toggles a .shrink class once window.scrollY passes 40px. That single class narrows the pill from 720px to 560px, raises it closer to the top, tightens the padding, and deepens both the background opacity and the shadow. Every one of those changes is driven by CSS transitions on width, top, padding, background, and box-shadow, so the JavaScript only flips a class while CSS animates the morph smoothly with a cubic-bezier ease.

The sliding active indicator

A .fp-pill element is created in JavaScript and appended behind the links. The movePill function reads the target link's offsetLeft and offsetWidth and applies them as a translateX and width, so the highlight glides to sit exactly under any link. It follows the mouse on mouseenter, snaps to the clicked link as the new active item, and returns to the active link when the cursor leaves the list via mouseleave. Because it animates transform and width rather than left, the motion is GPU-accelerated and stays at 60fps.

Staying correct on resize

Link positions change when the viewport resizes, so a resize listener re-measures and repositions the indicator under the current active link. On first paint the position is set inside a requestAnimationFrame callback to guarantee layout has been computed before measuring offsetLeft — measuring too early would place the pill at zero.

Responsive behavior

Below 560px the center link list is hidden with a media query, leaving the brand and the call-to-action button — the typical mobile collapse point where you would swap in a hamburger nav or a bottom nav. The CTA keeps a subtle hover lift so the primary action stays obvious at any size.

Customizing it

Change the two width values to control how dramatically the bar condenses, adjust the scrollY > 40 threshold to shrink sooner or later, and recolor the indicator's rgba background to match your accent. Because the shrink is just a class toggle, you can add more changes — hide the brand text, swap the logo, or fade in a search icon — purely by extending the .shrink rules in CSS.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA frosted pill navbar floats centered near the top of the page.
  2. 2
    Hover the linksA soft indicator slides under whichever link you point at.
  3. 3
    Click a linkThe indicator snaps to it and it becomes the active item.
  4. 4
    Scroll downThe whole pill narrows, rises, and deepens its glass background.
  5. 5
    Resize the windowThe indicator re-measures so it stays aligned under the active link.
  6. 6
    Tune the thresholdsAdjust the width values and scrollY trigger to taste.

Real-world uses

Common Use Cases

Floating nav over mesh heroes
Float a frosted glass navbar above a gradient mesh hero, shrinking its width and height with one class on scroll.
Product marketing sites
Offer an alternative to a full-width sticky header, with a sliding pill that follows the hovered and active link.
Portfolio menus
Top a portfolio hero with a minimal floating menu, using throttled passive scroll handling to keep the main thread free.
Documentation sections
Combine with a scroll spy nav for section tracking, with the pill indicator moving by transform.
Mobile fallback pairing
Swap to a hamburger nav under about 560 pixels, and study the transform-based sliding indicator as a reference.
Related: Keyboard-Navigable Icon Rail
See the Keyboard-Navigable Icon Rail for a related navigation pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

JavaScript only toggles a .shrink class when scrollY passes 40px; all the actual change — narrower width, higher top, tighter padding, denser background — lives in CSS transitions with a cubic-bezier ease. The scroll listener is passive and wrapped in requestAnimationFrame, so measuring and the class flip never block scrolling.

movePill reads the target link's offsetLeft and offsetWidth and applies them as a translateX and width on an absolutely-positioned pill behind the links. It animates transform and width (GPU-friendly) rather than the left property, so it glides smoothly under the hovered link and snaps to the active one on click.

offsetLeft and offsetWidth return zero until the browser has computed layout. Deferring the first movePill call to a requestAnimationFrame guarantees the links have been laid out, so the pill appears correctly under the initial active link instead of at the far left.

Yes. A resize listener calls movePill on the current active link whenever the viewport changes, recalculating its offset. Below 560px a media query hides the center links entirely, which is the natural breakpoint to swap in a hamburger or bottom-nav menu.

Render the links from an array and keep an activeIndex in state. Use a ref to the active link element and recompute the indicator's left/width in a layout effect (useLayoutEffect in React, onMounted plus a watcher in Vue, ngAfterViewInit in Angular). Attach the scroll and resize listeners in the same effect and return a cleanup that removes them. In Tailwind, build the pill with backdrop-blur, bg-white/10, and rounded-full utilities.

Yes. While the Floating Pill Nav snippet gives you one pattern to copy, the free Responsive Navbar Builder at webdevpuneet.com/navbar-builder/ designs a whole navigation bar: logo, links and dropdown menus, a mobile hamburger menu (dropdown panel, slide-in drawer or full screen) and a scroll effect (sticky, shrink, hide on scroll or transparent). It has six presets, a live preview that runs the real code, and exports HTML + CSS + vanilla JS, React, Tailwind, Vue 3 or Angular — or you can click Fork & Edit to keep editing it in My Code.