Navbar

Bootstrap · Lesson 11 of 28 6 min read Updated

The navbar is the bar at the top of most websites: logo on the left, links next to it, maybe a search box or a login button on the right. On phones those links fold away behind a "hamburger" button. Bootstrap's navbar component does all of this, including the folding, with HTML and class names.

In this lesson you will build a responsive navbar step by step, add a dropdown and a search form, colour it, and fix it to the top of the page.

How the navbar is built

A navbar has a few required pieces, each with its own class:

PieceClassPurpose
Wrappernavbar navbar-expand-lgThe bar, and the breakpoint where it stops folding
Inner containercontainer or container-fluidSpacing and width, like the rest of the page
Brandnavbar-brandLogo or site name, usually a link to the home page
Togglernavbar-togglerThe hamburger button shown on small screens
Collapsible areacollapse navbar-collapseEverything that hides on small screens
Linksnavbar-nav, nav-item, nav-linkThe menu itself

navbar-expand-lg means "expanded (links visible) from lg upwards, collapsed below". Use navbar-expand-md to expand earlier, or plain navbar-expand to never collapse. Without any navbar-expand-* class the navbar is always collapsed.

A responsive navbar

HTMLTry it yourself
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Navbar</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
  <nav class="navbar navbar-expand-lg bg-body-tertiary" aria-label="Main navigation">
    <div class="container">
      <a class="navbar-brand fw-bold" href="#home">Jaipur Jewels</a>
      <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#mainMenu"
              aria-controls="mainMenu" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="mainMenu">
        <ul class="navbar-nav me-auto mb-2 mb-lg-0">
          <li class="nav-item"><a class="nav-link active" aria-current="page" href="#home">Home</a></li>
          <li class="nav-item"><a class="nav-link" href="#rings">Rings</a></li>
          <li class="nav-item dropdown">
            <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">Collections</a>
            <ul class="dropdown-menu">
              <li><a class="dropdown-item" href="#kundan">Kundan</a></li>
              <li><a class="dropdown-item" href="#meenakari">Meenakari</a></li>
              <li><hr class="dropdown-divider"></li>
              <li><a class="dropdown-item" href="#bridal">Bridal sets</a></li>
            </ul>
          </li>
          <li class="nav-item"><a class="nav-link disabled" aria-disabled="true">Sale (soon)</a></li>
        </ul>
        <form class="d-flex" role="search">
          <input class="form-control me-2" type="search" placeholder="Search jewellery" aria-label="Search jewellery">
          <button class="btn btn-outline-success" type="submit">Search</button>
        </form>
      </div>
    </div>
  </nav>
  <main class="container py-4">
    <h1 class="h3">Handmade jewellery from the Pink City</h1>
    <p>Make the result panel narrower than 992px: the links fold behind the toggler button. Click it to open the menu.</p>
  </main>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

How it works:

  • The toggler uses data-bs-toggle="collapse" and data-bs-target="#mainMenu". Bootstrap's JavaScript opens and closes the element with that id, and updates aria-expanded so screen readers know whether the menu is open.
  • me-auto on the navbar-nav pushes the search form to the far end. To put the links themselves on the right, use ms-auto instead.
  • mb-2 mb-lg-0 adds space under the links only when they are stacked on small screens.
  • active with aria-current="page" marks the current page, visually and for screen readers.
  • The dropdown is a normal Bootstrap dropdown inside a nav-item. You will learn dropdowns fully in Dropdowns.

Colour schemes

Since Bootstrap 5.3, you colour a navbar with any background class and set the text scheme with data-bs-theme. For a dark navbar, add data-bs-theme="dark" so the links, the toggler icon and the dropdowns all switch to light-on-dark:

HTML
<!-- Dark grey -->
<nav class="navbar navbar-expand-lg bg-dark" data-bs-theme="dark"> ... </nav>

<!-- Brand colour -->
<nav class="navbar navbar-expand-lg bg-primary" data-bs-theme="dark"> ... </nav>

<!-- Follows the page theme (light or dark) -->
<nav class="navbar navbar-expand-lg bg-body-tertiary"> ... </nav>

bg-body-tertiary is a good default: it is a soft grey in light mode and a dark grey in dark mode, with no extra work.

Brand with a logo, and navbar text

The brand can hold an image, text, or both. Keep the logo small and give it real alt text if it is the only thing in the link. navbar-text styles plain text so it lines up with the links.

HTML
<nav class="navbar bg-dark" data-bs-theme="dark">
  <div class="container">
    <a class="navbar-brand d-flex align-items-center gap-2" href="/">
      <img src="https://course.ethicscomputer.in/assets/samples/icon.svg" alt="" width="32" height="32">
      Kochi Kitchen
    </a>
    <span class="navbar-text">Open today 11 am to 11 pm</span>
  </div>
</nav>

Here the image has alt="" because the text "Kochi Kitchen" already names the link. An empty alt avoids screen readers saying the name twice.

Fixed and sticky navbars

There are three ways to keep a navbar in place:

  • fixed-top fixes it to the top of the screen. It is removed from the normal page flow, so the page content slides under it. Add padding to the top of <body> (about the navbar's height) to compensate.
  • sticky-top scrolls with the page until it reaches the top, then sticks. It keeps its place in the layout, so no padding is needed. This is usually the better choice.
  • fixed-bottom fixes it to the bottom, for app-style tab bars on phones.
HTMLTry it yourself
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Sticky navbar</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
  <div class="bg-warning-subtle text-center small py-1">Free delivery in Lucknow on orders above ₹499</div>
  <nav class="navbar navbar-expand-md bg-dark sticky-top" data-bs-theme="dark" aria-label="Main navigation">
    <div class="container">
      <a class="navbar-brand" href="#top">Awadh Bakers</a>
      <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#bakeryNav"
              aria-controls="bakeryNav" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="bakeryNav">
        <ul class="navbar-nav ms-auto">
          <li class="nav-item"><a class="nav-link" href="#cakes">Cakes</a></li>
          <li class="nav-item"><a class="nav-link" href="#cookies">Cookies</a></li>
          <li class="nav-item"><a class="nav-link" href="#contact">Contact</a></li>
        </ul>
      </div>
    </div>
  </nav>
  <main class="container py-4">
    <h1 class="h3">Scroll down</h1>
    <p style="height: 1500px">The yellow strip scrolls away, but the dark navbar sticks to the top of the screen.</p>
  </main>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

Common mistakes

  • Toggler id mismatch. data-bs-target="#mainMenu" must match id="mainMenu" exactly, including capital letters.
  • No navbar-expand-* class. The navbar stays collapsed even on a wide screen.
  • Forgetting the JavaScript bundle. The toggler and dropdowns do nothing without it.
  • Using fixed-top without body padding. The first heading hides under the navbar. Use sticky-top, or add padding.
  • White text on a light navbar. With a dark background, add data-bs-theme="dark" instead of colouring each link by hand.

Key points

  • A navbar needs navbar, a navbar-expand-* breakpoint, a container, a navbar-brand, a navbar-toggler and a collapse navbar-collapse area.
  • The toggler's data-bs-target must match the collapsible area's id.
  • navbar-nav, nav-item and nav-link build the links; active plus aria-current="page" marks the current page.
  • Colour a navbar with background classes and use data-bs-theme="dark" for light text.
  • sticky-top keeps the navbar visible without hiding content; fixed-top needs body padding.

Exercise

Build a navbar for "Rohtak Robotics Club". It should have a primary-coloured background with light text, the brand on the left, and these links aligned to the right: Home (current page), Events, Projects, and a "Join" dropdown with two items (Students, Mentors). It should collapse below the md breakpoint and stick to the top while scrolling.

Show solution
HTML
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Rohtak Robotics Club</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
  <nav class="navbar navbar-expand-md bg-primary sticky-top" data-bs-theme="dark" aria-label="Main navigation">
    <div class="container">
      <a class="navbar-brand" href="#home">Rohtak Robotics Club</a>
      <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#clubNav"
              aria-controls="clubNav" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="clubNav">
        <ul class="navbar-nav ms-auto">
          <li class="nav-item"><a class="nav-link active" aria-current="page" href="#home">Home</a></li>
          <li class="nav-item"><a class="nav-link" href="#events">Events</a></li>
          <li class="nav-item"><a class="nav-link" href="#projects">Projects</a></li>
          <li class="nav-item dropdown">
            <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">Join</a>
            <ul class="dropdown-menu dropdown-menu-end">
              <li><a class="dropdown-item" href="#students">Students</a></li>
              <li><a class="dropdown-item" href="#mentors">Mentors</a></li>
            </ul>
          </li>
        </ul>
      </div>
    </div>
  </nav>
  <main class="container py-4"><h1 class="h3">Welcome</h1></main>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

navbar-expand-md sets the collapse point, ms-auto moves the links right, data-bs-theme="dark" gives light text on the primary background, and dropdown-menu-end keeps the last dropdown inside the screen.

Quick Quiz

1. What does navbar-expand-lg control?

2. The toggler button does nothing when clicked. What is a likely cause?

3. How do you make a bg-dark navbar show light text in Bootstrap 5.3?

4. Why is sticky-top often better than fixed-top?

Learn Bootstrap with a mentor

Free lessons get you started. Our Full Stack Web Development training adds real projects and code reviews from working developers.

  • Project-based learning
  • Mentor code reviews
  • Free counselling call