Floating navbar for React and Next.js: the free ones first, then a pill that opens
If you want a floating navbar that holds your links and hides when people scroll down, use a free one. Aceternity UI's Floating Navbar does exactly that and installs with the shadcn CLI, and floating-pill-nav.tsx further down is a plain Tailwind version with no library. The Dynamic Island is for a different job: a black floating pill that opens into page search or shows a live notification. It doesn't hide on scroll and it doesn't hold your own list of links.

By buying you agree to the Terms.
- Download right after paying
- Use it in client projects
- Won't run on the listed stack? We fix it or refund you
Ready forCursorv0Lovableshadcn CLI
Use it in Next.js
import type { ReactNode } from "react";
import "./globals.css";
import { IslandNav } from "@/components/island-nav";
import { SiteFooter } from "@/components/site-footer";
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en">
<body className="min-h-dvh bg-neutral-100 text-neutral-900">
<IslandNav />
{/* room for the island: 76 px tall at top 16 (60 px on phones) */}
<main className="mx-auto max-w-5xl px-4 pt-28">{children}</main>
<SiteFooter />
</body>
</html>
);
}@import "tailwindcss";
/* The island needs no extra rule here. See the Tailwind v4 section if you keep the zip's demo stage. */"use client";
import { useRouter } from "next/navigation";
import DynamicIsland from "@/components/DynamicIsland";
import { PAGES } from "@/lib/pages";
export function IslandNav() {
const router = useRouter();
return (
// The island positions itself (absolute, centred, top px), so a fixed,
// zero-height header keeps it floating while the page scrolls.
<header className="fixed inset-x-0 top-0 z-40">
<DynamicIsland
size="auto"
top={16}
tabs={["search", "notify"]}
accent="#C6FF3D"
items={PAGES.map((page) => page.label)}
resultTag="Page"
searchPlaceholder="Search pages"
avatar="A"
notificationTitle="Invoice paid"
notificationText="INV-2041 was paid a minute ago"
notificationAction="Open"
onHome={() => router.push("/")}
onSelect={(label) => {
const page = PAGES.find((p) => p.label === label);
if (page) router.push(page.href);
}}
onNotificationAction={() => router.push("/invoices")}
/>
</header>
);
}export const PAGES = [
{ label: "Dashboard", href: "/dashboard" },
{ label: "Projects", href: "/projects" },
{ label: "Invoices", href: "/invoices" },
{ label: "Team", href: "/team" },
{ label: "Settings", href: "/settings" },
{ label: "Help", href: "/help" },
];import Link from "next/link";
import { PAGES } from "@/lib/pages";
// The island's search results are buttons, not links.
// Keep real links on every page for crawlers and for people who never open search.
export function SiteFooter() {
return (
<footer className="mt-24 border-t px-4 py-10">
<nav aria-label="Pages" className="mx-auto flex max-w-5xl flex-wrap gap-x-6 gap-y-2 text-sm">
{PAGES.map((page) => (
<Link key={page.href} href={page.href} className="hover:underline">
{page.label}
</Link>
))}
</nav>
</footer>
);
}Good to know
- What we ran on Oct 25 2026: every file on this page type-checked with TypeScript 5.9.3 against the shipped DynamicIsland.tsx, framer-motion 14.6.0, motion 14.6.0, React 19.3.1, @types/react 19.3.0 and Next.js 15.5.28's types. A wrong island tab name failed tsc, so the props really are checked. We did not run next build or a dev server for these files.
- We also rendered the island and floating-pill-nav.tsx to static HTML with React's server renderer and read them in headless Chromium with CSS compiled by Tailwind 4.3.3. With two tabs the closed island measured 358 x 76 px at size="regular" and 232 x 60 px at size="compact". The free pill measured 346 px wide with a brand and four links, and neither page scrolled sideways at 390 px. No JavaScript ran in that check, so the morphing, search and size="auto" switch were not exercised there.
- What we didn't run: Next.js 16, a real phone, Safari or Firefox, a screen reader, or your own routes.
- The island holds Home plus up to three fixed icons (search, music, notify) and an avatar. You can't add your own link items to it. At 390 px the compact island is 280 px wide with all three icons and 48 px narrower for each icon you leave out, so it fits a phone, but it is not a list of page links.
- The island's search results are buttons that call onSelect, not links. Keep a plain list of links somewhere on the page, as the footer above does, for crawlers and for people who never open search.
- The island's CSS names Space Grotesk and JetBrains Mono but doesn't load them. Load them with next/font or change the names in dynamic-island.css. Otherwise it falls back to system-ui.
Free floating navbar in React: plain Tailwind, no library
- A floating navbar is mostly three classes: fixed so it stays put, rounded-full so it reads as a pill, and a translucent background with backdrop-blur so the page shows through. floating-pill-nav.tsx below is that, with Next.js Link for client-side navigation and aria-current on the active link.
- In our render at 390 px the pill was 346 px wide with a brand and four links, so it fits a phone without a menu button. With more links than that, wrap them or move them into a menu below sm.
- It doesn't hide on scroll. If you want that, our post Hide Navbar on Scroll Down in React and Tailwind (qodesign.dev/blog/hide-navbar-on-scroll-react-tailwind) adds it to a bar like this one.
"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
const LINKS = [
{ label: "Features", href: "/features" },
{ label: "Docs", href: "/docs" },
{ label: "Blog", href: "/blog" },
{ label: "Pricing", href: "/pricing" },
];
// Free route: a floating pill navbar in plain Tailwind. No library.
export function FloatingPillNav() {
const pathname = usePathname();
return (
<header className="fixed inset-x-0 top-4 z-40 flex justify-center px-4">
<nav
aria-label="Main"
className="flex items-center gap-1 rounded-full border border-black/10 bg-white/80 p-1.5 shadow-lg shadow-black/5 backdrop-blur-md"
>
<Link href="/" className="px-3 text-sm font-semibold">
Acme
</Link>
{LINKS.map((link) => (
<Link
key={link.href}
href={link.href}
aria-current={pathname === link.href ? "page" : undefined}
className="rounded-full px-3 py-1.5 text-sm text-neutral-600 hover:bg-black/5 hover:text-neutral-900 aria-[current=page]:bg-neutral-900 aria-[current=page]:text-white"
>
{link.label}
</Link>
))}
</nav>
</header>
);
}Aceternity floating navbar: free, hides on scroll
- Aceternity UI describes its free Floating Navbar as "A sticky Navbar that hides on scroll, reveals when scrolled up." It installs with npx shadcn@latest add @aceternity/floating-navbar, takes className and navItems ({ name, link, icon }), and its one dependency is motion. We read the page and the registry file on Oct 25 2026.
- Things we found in the file itself. It starts hidden: the bar shows only after you have scrolled past the first 5% of the page and then scroll back up, so on a page too short to scroll it never appears. Its links are plain a tags, so in Next.js each click is a full page load; swap them for Link if you want client-side navigation. The Login button at the end is fixed text with no handler, so you edit it.
- One type error to expect in a React 19 app. In our check with @types/react 19.3.0, the installed floating-navbar.tsx failed tsc with "Cannot find namespace 'JSX'" on its icon type. Changing icon?: JSX.Element to icon?: React.ReactNode fixed it, and site-nav.tsx below then type-checked.
- Aceternity also has a free Resizable Navbar, "A navbar that shrinks and blurs once the page scrolls, with a mobile drawer", installed with npx shadcn@latest add @aceternity/resizable-navbar. For a marketing site with real links, either of these fits better than the island.
"use client";
import { FloatingNav } from "@/components/ui/floating-navbar";
// After: npx shadcn@latest add @aceternity/floating-navbar
export function SiteNav() {
return (
<FloatingNav
navItems={[
{ name: "Home", link: "/" },
{ name: "Docs", link: "/docs" },
{ name: "Blog", link: "/blog" },
]}
/>
);
}Floating pill navbar that opens: where the Dynamic Island fits
- The Dynamic Island is a black pill that floats at the top of its positioned parent (the top prop sets the gap in px). Tap search and it widens into a search box with results; trigger a notification and it grows into a toast that collapses on its own; the music state turns it into a small player. The width, height and corner radius morph with a spring in framer-motion.
- That suits an app header more than a site header: a dashboard where search is the main way around, or a product that has one live event worth showing, like a paid invoice or a new order. The files above put it in a fixed, zero-height header so it keeps floating while the page scrolls, with search over your pages and a footer of real links.
- What it won't do: hide on scroll, hold a logo on the left, or show a row of text links. If your floating navbar needs those, use one of the free ones above.
Floating navbar in Next.js: Tailwind v4 notes
- The Dynamic Island download is a Vite project set up with Tailwind CSS 3.4, React 18 and framer-motion ^11.11.0. The component styles itself in dynamic-island.css with qdi- classes, and every selector in that file starts with a qdi- class, so it doesn't touch the rest of your app. Our CSS leak audit of every paid piece rated it clean, and we re-read the file on Oct 25 2026 to check.
- Our Tailwind v4 check of every piece (Oct 25 2026, Tailwind 4.3.3 against 3.4.19) rated the island a one-line fix: "The island label, subtitle and controls (font-sans on main and children, 4 elements) render in the system sans instead of Space Grotesk." Those elements are the demo stage in the zip's App.tsx. The navbar on this page doesn't use the stage, so it needs nothing.
- If you do keep the stage: in a plain Tailwind v4 app you can point @config at the zip's tailwind.config.js. In an app with a UI kit or its own fonts in globals.css (shadcn, daisyUI, HeroUI), don't. The check's Oct 25 correction found @config there either does nothing or switches the whole app's sans font. Add a class to the stage's main element (we used qdi-stage) and put .qdi-stage { font-family: "Space Grotesk", system-ui, sans-serif; } in app/globals.css instead.
- React 19: the snippets type-checked against React 19.3.1 and @types/react 19.3.0, while the piece's package.json lists React 18. framer-motion 14.6.0 lists react ^18.0.0 || ^19.0.0 as its peer range.
Install
- Copy from the zipPut
react/src/componentsintosrc/, thennpm i framer-motion. - Or ask your AIPaste PROMPT.md into Cursor, Lovable or v0.
Props
- tabs
- icons next to Home: "search", "music", "notify"
- items / onSelect
- what search finds, and the pick (push the route here)
- onHome
- the Home icon
- size
- "regular", "compact" or "auto" (compact under 640 px)
- top
- px from the top of the positioned parent
- avatar
- any short node at the right end
- notificationTitle / notificationText / notificationAction
- the bell state's text; onNotificationAction for its button
- onStateChange
- idle, notify, music or search
- accent
- any CSS colour, including a CSS variable
How qodesign compares
- qodesign vs Hover.devHover.dev is best for: animated website sections you copy and paste.
- qodesign vs Cult UICult UI is best for: free animated shadcn components and device mockups.
All comparisons, with prices read on each library's own site.
Questions
How do I make a floating navbar in React?
Put the nav in a fixed container, centre it, give it rounded-full and a translucent background with backdrop-blur. floating-pill-nav.tsx above is a complete version with Next.js Link.
Is there a free floating navbar component for React?
Yes. Aceternity UI's Floating Navbar and Resizable Navbar are free and install with the shadcn CLI. The plain Tailwind file on this page needs no library at all.
How do I hide a navbar on scroll down and show it on scroll up?
Aceternity's Floating Navbar does it with motion's useScroll. For a plain version, our post Hide Navbar on Scroll Down in React and Tailwind walks through it. The Dynamic Island doesn't hide on scroll.
Why doesn't Aceternity's floating navbar show when the page loads?
Its code keeps it hidden until the page has been scrolled past 5% and you scroll back up. On a short page it never shows. Change that check if you want it visible at the top.
Can the Dynamic Island hold my own navigation links?
No. It has Home, up to three fixed icons and an avatar. Your pages go into its search items, and plain links belong in the footer or the page.
Can Cursor or v0 add it for me?
Yes. Each download has a PROMPT.md. Paste it into Cursor, Lovable, v0 or Claude Code and it fits the piece into your app.
Can I use it in client work?
Yes, in personal and client projects. You can't resell the code itself as a kit.