Skip to content
‹ Journal

How to Create a Good Navbar

A good navbar is essential for a good user experience. Here's how to create one.

Gustavo J.

· 10 min read · Design

Types of Navbars

There are many types of navbars, but the most common ones are:

  • Static Navbar: The navbar stays in the same position on the page.
  • Sticky Navbar: The navbar stays at the top of the page when the user scrolls down.
  • Transparent Navbar: The navbar is transparent and becomes opaque when the user scrolls down.
  • Hamburger Menu: The navbar is hidden and appears when the user clicks on the hamburger icon.
  • Float Navbar: The navbar floats on the page and appears when the user scrolls down.
  • Circular Navbar: The navbar is circular and appears when the user scrolls down.
  • Split Navbar: The navbar is split in the middle and appears when the user scrolls down.

Useful Libraries

  • Framer Motion: For animations and transitions.
  • Tailwind CSS: For styling and layout.
  • Lucide React: For icons.
  • NavKit: For navbar components.
  • Next.js: For routing and server-side rendering.
  • Shadcn UI: For UI components.
  • Radix UI: For Symbols.

Now How Looks a Good Navbar Code?

tsx
export function FloatingNav() {
  const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
  const pathname = usePathname();

  useEffect(() => {
    if (mobileMenuOpen) {
      document.body.style.overflow = "hidden";
    } else {
      document.body.style.overflow = "unset";
    }
  }, [mobileMenuOpen]);

  return (
    <div className="fixed top-8 left-0 right-0 z-100 flex justify-center px-6">
      <header className="pill-nav h-[48px] px-8 rounded-full flex items-center justify-between w-full max-w-[720px] gap-4">
        <Link href="/" className="text-[14px] font-bold tracking-tight shrink-0">
          GUSTAVO J.
        </Link>

        <nav className="hidden md:flex items-center gap-1 relative">
          {NAV_LINKS.map((link) => {
            const isActive = pathname === link.href;
            return (
              <Link
                key={link.href}
                href={link.href}
                className={`relative px-4 py-2 text-[11px] font-bold tracking-widest uppercase transition-colors duration-300 z-10 ${isActive ? "text-white" : "text-white/40 hover:text-white"
                  }`}
              >
                {isActive && (
                  <motion.div
                    layoutId="nav-liquid"
                    className="absolute inset-0 bg-white/10 rounded-full -z-10"
                    transition={{ type: "spring", bounce: 0.3, duration: 0.6 }}
                  />
                )}
                {link.label}
              </Link>
            );
          })}
        </nav>

        <button
          onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
          className="md:hidden p-2 text-white/80"
        >
          {mobileMenuOpen ? <X size={16} /> : <Menu size={16} />}
        </button>

        <div className="hidden md:block">
          <Link href="/contact" className="text-[11px] font-black uppercase text-primary tracking-tighter hover:text-white transition-colors">
            Contact
          </Link>
        </div>

      </header>

      <AnimatePresence>
        {mobileMenuOpen && (
          <motion.div
            initial={{ opacity: 0, scale: 0.95 }}
            animate={{ opacity: 1, scale: 1 }}
            exit={{ opacity: 0, scale: 0.95 }}
            className="fixed inset-0 bg-black/95 z-90 flex flex-col items-center justify-center p-12"
          >
            <nav className="flex flex-col gap-8 text-center">
              {NAV_LINKS.map((link, i) => (
                <motion.div
                  key={link.href}
                  initial={{ opacity: 0, y: 10 }}
                  animate={{ opacity: 1, y: 0 }}
                  transition={{ delay: i * 0.05 }}
                >
                  <Link
                    href={link.href}
                    onClick={() => setMobileMenuOpen(false)}
                    className="text-4xl font-bold tracking-tighter"
                  >
                    {link.label}
                  </Link>
                </motion.div>
              ))}
              <button
                onClick={() => setMobileMenuOpen(false)}
                className="mt-12 p-4 rounded-full bg-white/5 border border-white/10"
              >
                <X size={24} />
              </button>
            </nav>
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  );
}

Here you can see a sample code of a good navbar, but you can customize it as you wish. It's important to menction: this code is from my portfolio, so you can use it as a reference.

Now, let's talk about the code itself. This code is a floating navbar, which means it stays at the top of the page when the user scrolls down. It also has a mobile menu, which is hidden by default and appears when the user clicks on the hamburger icon. Also, it has a liquid effect, which means it expands when the user hovers over it.