Lesson 7 of 12

Bootstrap Navbar

The navbar is the navigation bar at the top of most websites. A Bootstrap navbar handles the tricky part for you: on wide screens the links sit in a row, and on narrow screens they fold into a “hamburger” button that opens a menu. In this lesson you will build one step by step and learn what each class and attribute does.

Bootstrap navbar structure

A navbar is made of a few nested parts. It looks like a lot of markup at first, but each part has one job:

PartJob
<nav class="navbar navbar-expand-md">The bar. navbar-expand-md means “show the full menu from the md breakpoint (768px) up; collapse it below”.
container or container-fluidAligns the navbar content with the rest of the page.
navbar-brandYour site name or logo, usually a link to the home page.
navbar-togglerThe menu button shown on small screens. Its data-bs-target points to the collapsible part.
collapse navbar-collapseThe part that hides and shows. Its id must match the toggler’s target.
navbar-nav, nav-item, nav-linkThe list of links.

The toggler uses Bootstrap’s Collapse JavaScript, so this is the first lesson where you need bootstrap.bundle.min.js before </body>. Without it, the menu button does nothing.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>A responsive navbar</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
</head>
<body>
<nav class="navbar navbar-expand-md bg-body-tertiary" aria-label="Main navigation">
  <div class="container">
    <a class="navbar-brand fw-bold" href="#">Kaveri Tours</a>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#mainNav" aria-controls="mainNav" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="mainNav">
      <ul class="navbar-nav ms-auto mb-2 mb-md-0">
        <li class="nav-item"><a class="nav-link active" aria-current="page" href="#">Home</a></li>
        <li class="nav-item"><a class="nav-link" href="#">Tours</a></li>
        <li class="nav-item"><a class="nav-link" href="#">Gallery</a></li>
        <li class="nav-item"><a class="nav-link" href="#">Contact</a></li>
      </ul>
    </div>
  </div>
</nav>
<main class="container py-4">
  <h1 class="h3">River tours in Tamil Nadu</h1>
  <p>Make the preview narrower than 768px and the links fold into the menu button. Click it to open the menu.</p>
</main>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

A few details are worth noticing. ms-auto on the list pushes the links to the right (see Bootstrap Flex and Alignment). The current page link has active for the visual style and aria-current="page" so screen readers announce it as the current page. The toggler’s aria-controls, aria-expanded and aria-label describe the button to assistive technology; Bootstrap updates aria-expanded automatically when the menu opens.

Tip: Pick the expand breakpoint by counting your links. Four short links fit on a tablet, so navbar-expand-md is fine. Seven links and a search box need more room, so use navbar-expand-lg. A Bootstrap navbar with no navbar-expand-* class is always collapsed, even on desktops.

Colours and dark navbars

Set the background of a Bootstrap navbar with any background utility: bg-body-tertiary for a light grey bar that also adapts to dark mode, or bg-dark/bg-primary for a strong colour. When the background is dark, add data-bs-theme="dark" to the navbar so the link and toggler icon colours switch to light ones.

Watch out: In Bootstrap 5.3, navbar-dark is deprecated. Use data-bs-theme="dark" on the <nav> instead. Older tutorials also use data-toggle and data-target; in Bootstrap 5 they must be data-bs-toggle and data-bs-target, or the toggler silently fails.

A navbar can hold more than links. A dropdown groups related pages under one item, using dropdown, dropdown-toggle, data-bs-toggle="dropdown" and a dropdown-menu list. A short search form can sit at the end with d-flex and role="search". Use navbar-text for plain text such as “Call us” so it lines up with the links.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Dark navbar with a dropdown and search</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
</head>
<body>
<nav class="navbar navbar-expand-lg bg-dark" data-bs-theme="dark" aria-label="Shop navigation">
  <div class="container-fluid">
    <a class="navbar-brand" href="#">Kanchi Silks</a>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#shopNav" aria-controls="shopNav" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="shopNav">
      <ul class="navbar-nav me-auto mb-2 mb-lg-0">
        <li class="nav-item"><a class="nav-link active" aria-current="page" href="#">New arrivals</a></li>
        <li class="nav-item dropdown">
          <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">Sarees</a>
          <ul class="dropdown-menu">
            <li><a class="dropdown-item" href="#">Kanjivaram</a></li>
            <li><a class="dropdown-item" href="#">Chettinad cotton</a></li>
            <li><hr class="dropdown-divider"></li>
            <li><a class="dropdown-item" href="#">All sarees</a></li>
          </ul>
        </li>
        <li class="nav-item"><a class="nav-link" href="#">Dhotis</a></li>
      </ul>
      <form class="d-flex" role="search" id="searchForm">
        <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
        <button class="btn btn-outline-light" type="submit">Search</button>
      </form>
    </div>
  </div>
</nav>
<div class="container py-4">
  <p>This navbar expands from 992px (lg). In a narrower preview, open the menu button first, then try the "Sarees" dropdown.</p>
  <p id="searchOut" class="text-body-secondary"></p>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<script>
// Demo only: show the search term instead of loading a results page
document.getElementById('searchForm').addEventListener('submit', (event) => {
  event.preventDefault();
  const term = event.target.querySelector('input').value.trim();
  document.getElementById('searchOut').textContent = term ? 'You searched for: ' + term : 'Type something to search.';
});
</script>
</body>
</html>

Fixed and sticky navbars

fixed-top pins the navbar to the top of the window. It is taken out of the normal flow, so the page content slides underneath it; add top padding to <body> to compensate. sticky-top is usually nicer: the navbar scrolls with the page until it reaches the top, then sticks there, and nothing is hidden underneath.

For navigation inside a page section, such as switching between “Details” and “Reviews”, use the simpler nav component. Add nav-tabs for tabs or nav-pills for rounded buttons. These are only styles; to switch content panes you add the Tab JavaScript (data-bs-toggle="tab"), or link each item to a separate page.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Nav tabs and pills</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
</head>
<body>
<div class="container py-4">
  <ul class="nav nav-tabs mb-4">
    <li class="nav-item"><a class="nav-link active" aria-current="page" href="#">Details</a></li>
    <li class="nav-item"><a class="nav-link" href="#">Itinerary</a></li>
    <li class="nav-item"><a class="nav-link" href="#">Reviews</a></li>
  </ul>
  <ul class="nav nav-pills nav-fill">
    <li class="nav-item"><a class="nav-link active" aria-current="page" href="#">All</a></li>
    <li class="nav-item"><a class="nav-link" href="#">Beaches</a></li>
    <li class="nav-item"><a class="nav-link" href="#">Temples</a></li>
    <li class="nav-item"><a class="nav-link" href="#">Hills</a></li>
  </ul>
</div>
</body>
</html>

nav-fill stretches the pills to fill the width. For larger sites, Bootstrap also offers an offcanvas navbar, where the mobile menu slides in from the side. It uses the same idea with offcanvas classes instead of collapse. Whichever pattern you use, wrap navigation in a <nav> element with a clear aria-label, as explained in HTML Semantic Elements.

Further reading

Key takeaways

  • A navbar is navbar navbar-expand-{breakpoint} with a brand, a toggler and a collapse navbar-collapse section.
  • The toggler's data-bs-target must match the collapse element's id, and the JavaScript bundle must be loaded.
  • Mark the current page with active and aria-current="page".
  • For dark navbars, use a dark background plus data-bs-theme="dark"; navbar-dark is deprecated.
  • Use sticky-top for a navbar that stays visible, and nav-tabs/nav-pills for in-page navigation.

Quick quiz

Check what you learned – pick an answer.

1. What does navbar-expand-lg mean?

2. You click the navbar toggler and nothing happens. Which is the most likely cause?

3. How do you get light link text on a bg-dark navbar in Bootstrap 5.3?

Practice exercise

Build a sticky, primary-coloured navbar for a coaching centre in Tirunelveli. It should have a brand, three links (Courses, Results, Contact) aligned to the right with Courses marked as the current page, a toggler that collapses the links below 768px, and light text suitable for the blue background.

Show a hint

Use navbar navbar-expand-md bg-primary sticky-top with data-bs-theme="dark", and remember the JavaScript bundle.

Show the solution
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Coaching centre navbar</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
</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="#">Nellai Academy</a>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#academyNav" aria-controls="academyNav" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="academyNav">
      <ul class="navbar-nav ms-auto">
        <li class="nav-item"><a class="nav-link active" aria-current="page" href="#">Courses</a></li>
        <li class="nav-item"><a class="nav-link" href="#">Results</a></li>
        <li class="nav-item"><a class="nav-link" href="#">Contact</a></li>
      </ul>
    </div>
  </div>
</nav>
<main class="container py-4">
  <h1 class="h3">Courses</h1>
  <p>Evening classes for school students and weekend batches for exam preparation.</p>
</main>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

Progress is saved in this browser only.