What Is a Bootstrap Header?
Every header example in the docs is really a navbar. Bootstrap’s own documentation calls that component a “responsive navigation header”, and the header element around it is ordinary HTML that gives the bar a place in the page structure.
The navbar ships inside the Bootstrap CSS framework, so the styles and the Collapse and Offcanvas scripts all come from one package.
As of October 2026, the official docs list v5.3.8 as the current release, which shipped on August 25, 2025 (Bootstrap blog). Every class name in this article targets the 5.3 line.
Searches for a Bootstrap header also pull in the Bootstrap 3 .page-header class, a spacing wrapper around a page heading from a much older major version. Some people mean the hero section, the large banner that sits under the header. The .card-header strip at the top of a card gets mixed in too. MDB and CoreUI header components are different again, since they ship their own markup (MDB uses data-mdb-* attributes).
The navbar component has its own guide if you want it covered in isolation, the Bootstrap navbar one.
How to Build a Bootstrap Header Step by Step
Skip any one of these pieces and the menu usually stops working in a way that takes a while to trace.
- Add the HTML5 doctype and the viewport meta tag. Load the CSS in the head and the bundle script before the closing body tag, from jsDelivr (bootstrap@5.3.8).
- Open a header element, then a nav with the classes navbar, navbar-expand-lg, and bg-body-tertiary.
- Add a div with container-fluid inside the nav. Use container instead for a fixed-width layout.
- Add the brand: an a tag with navbar-brand, holding text or an img with explicit width and height.
- Add the toggler: a button with navbar-toggler, data-bs-toggle=”collapse”, data-bs-target=”#navbarNav”, aria-controls=”navbarNav”, aria-expanded=”false”, and aria-label=”Toggle navigation”. Put a span with navbar-toggler-icon inside it.
- Add a div with collapse and navbar-collapse and the id navbarNav. Inside it goes a ul.navbar-nav, where each link is an li.nav-item holding an a.nav-link. The current page gets the active class and aria-current=”page”.
The data-bs-target value and the collapse id must match exactly. A mismatch stops the menu from opening, and it’s the first thing I check when a toggler does nothing.
The bundle script includes Popper, which dropdowns need, along with popovers and tooltips. A header without a dropdown can load bootstrap.min.js alone and skip Popper, per the Bootstrap 5.3 docs.
Using a header element instead of a div has a practical effect. Placed directly in the body, it is exposed to assistive technology as the page banner, and the nav inside it as a navigation landmark.
How a Bootstrap Header Collapses on Small Screens
The navbar-expand-{breakpoint} class sets the width at which the links spread out in a row. Below that width they sit behind the toggler inside the collapse wrapper.
Choosing the breakpoint
Each breakpoint has its own expand class, with widths taken from the 5.3 breakpoints docs.
- sm: 576px and up
- md: 768px and up
- lg: 992px and up
- xl: 1200px and up
- xxl: 1400px and up
Without an expand class the header collapses at every width, and plain navbar-expand does the opposite, so the links never fold.
These widths rest on min-width CSS media queries and a mobile-first approach. The collapsed layout is the base style, and the row layout is the override.
Pick the breakpoint from the longest realistic label set, not from device names. If the links wrap onto a second row at some width, move the expand class up one step.
Toggler and Collapse plugin
Bootstrap’s plugins have no special fallback when JavaScript is disabled (Bootstrap 5.3 docs). A header that starts collapsed stays collapsed.
The navbar extends the Collapse and Offcanvas plugins, and the collapse animation respects the prefers-reduced-motion setting.
Markup order sets where the toggler lands. After the brand, it sits on the far right. Put it before the brand and it moves to the left, so reversing the markup flips it.
The three-line icon is the familiar hamburger menu icon. The navbar-toggler-icon class draws it as a background SVG, so no icon font is involved.
What Can You Put Inside a Bootstrap Header?
Most of what a header needs has built-in support. That covers the brand, links, dropdowns, search forms and plain text, and flex and spacing utilities handle the rest.
The brand is navbar-brand on an anchor, holding text, an image or both. Links go in a navbar-nav list of nav-link items. A search form is a d-flex form with role=”search”, with buttons alongside it. For a short string such as a phone number or login status, navbar-text does the job.
Immediate children of the navbar use flex layout and default to justify-content: space-between (Bootstrap 5.3 docs). Add me-auto to the link list to keep links on the left and push the search form to the right.
Dropdowns need a wrapper. An li.nav-item with the dropdown class surrounds a nav-link that carries dropdown-toggle and data-bs-toggle=”dropdown”, the same pattern as the standalone Bootstrap dropdown.
Popper does not position dropdowns inside a navbar, since dynamic positioning is not needed there. They open on click, never on hover, and the docs describe that as an intentional design decision.
For icons, pick one set per header, such as the Bootstrap Icons library or Font Awesome. Mixing two sets makes stroke weights clash.
Icon links stack vertically inside a collapsed menu unless you wrap them in a d-flex container.
Keep the content short. A brand, a few links and a single primary action is plenty.
Fixed, Sticky, or Static: Positioning the Bootstrap Header
Use sticky-top on the header element for most pages. Reach for fixed-top only when you control the header height.
| Class | Stays in flow | Body padding needed | Scroll behavior |
|---|
| Default (none) | Yes | No | Scrolls away with the page |
| .fixed-top | No | Yes | Stays at the top of the viewport |
| .sticky-top | Yes | No | Scrolls, then pins at the top |
| .sticky-lg-top | Yes | No | Pins only at 992px and up |
Bootstrap’s z-index scale sets sticky at 1020 and fixed at 1030, below offcanvas at 1045 and modals at 1055 (Bootstrap 5.3 docs). A modal opens over either header, which is the behavior you want.
A fixed header leaves the document flow, and the docs warn it may need padding-top on the body to prevent overlap. Set the padding to the rendered header height, measured in dev tools.
Anchor links need the same value in scroll-padding-top on the html element. Otherwise the target heading lands under the bar.
Sticky has one catch. position: sticky only works inside its parent, so a sticky-top class on a nav that sits in a header element no taller than the nav never pins.
Put the class on the header element, and make that element a direct child of the body.
A sticky header keeps the menu within reach on long pages, the pattern usually called sticky navigation.
How to Change the Bootstrap Header Color and Add Dark Mode
Put data-bs-theme=”dark” on the nav and pick a background with a bg-* utility. That is the 5.3 method, and it replaces the older navbar-dark class.
The Bootstrap 5.3 navbar docs show a few combinations that work. A dark bar uses bg-dark with border-bottom and border-body, plus data-bs-theme=”dark”. A colored bar can use bg-primary with the same dark attribute. For a pale custom bar, set an inline background-color of #e3f2fd and pair it with data-bs-theme=”light”.
The attribute applies to whatever element carries it. On the html element it themes the whole page, and on the nav alone it gives a dark header over a light page. Dropdowns inside the nav follow it.
The history is a little messy. v5.2.0 moved navbar theming to CSS variables scoped to .navbar and deprecated navbar-light, and v5.3.0 then deprecated navbar-dark in favor of the attribute.
For a custom palette, override variables on one navbar instead of rewriting rules. Link, hover, active and brand colors each get their own variable, namely –bs-navbar-color, –bs-navbar-hover-color, –bs-navbar-active-color and –bs-navbar-brand-color.
Sass builds change the defaults at the source. $navbar-light-color and $navbar-dark-color set the base link colors.
Choose custom colors with contrast in mind. A tool that generates accessible color palettes narrows the options before you touch any CSS.
Bootstrap’s own documentation header is a working reference. Its light, dark and auto picker is built from the same navbar and dropdown components, and the color modes docs print its script.
Bootstrap ships no built-in color mode picker, and the attribute does not follow the operating system on its own. The docs suggest placing the toggler script at the top of the page to reduce flicker on reload.
A Sass option, $color-mode-type: media-query, makes modes follow prefers-color-scheme automatically. It also removes per-component theming, so a dark header on a light page needs the default data attribute approach.
Collapse Menu or Offcanvas Panel for the Mobile Header?
If the open menu stays short enough to fit under the bar, use the Collapse plugin. Once it outgrows that, switch to an offcanvas panel.
Both patterns sit in the same navbar, and both turn back into a normal bar at the breakpoint you set with navbar-expand-lg or a sibling class. Offcanvas navbars arrived in v5.1.0, so v5.0 snippets will not have them (Bootstrap migration notes).
Collapse menu
The collapse menu takes the least markup, just one toggler and one collapse wrapper. It works with every position class and opens in place, so the menu stays attached to the bar.
The downsides are spacing and length. Padding cannot go on the .collapse element, so spacing needs an inner wrapper. A long menu on a fixed header runs past the screen unless navbar-nav-scroll caps it, which starts scrolling at 75vh by default.
Offcanvas panel
The offcanvas panel works as a slide-in drawer with its own header, close button, and scrolling body.
Long menus scroll inside the panel, search and account actions get room, and a backdrop dims the page behind it. Esc closes it by default, and body scrolling is locked while it is open (Bootstrap 5.3 offcanvas docs).
It costs more markup, with a header, title, close button and body to write out. Only one offcanvas can show at a time, and margin or translate cannot go on the .offcanvas element.
The Bootstrap docs disagree with themselves on dark offcanvas panels. The navbar page’s dark example still uses navbar-dark, bg-dark, and text-bg-dark, while the offcanvas page marks that approach deprecated in v5.3.0 in favor of data-bs-theme=”dark”.
Use the attribute on the nav. The offcanvas sits inside the nav, so it inherits the theme.
Start with collapse. Switch to offcanvas the first time the open menu covers more than half the screen.
How to Make a Bootstrap Header Accessible
Start with a skip link. Add an a tag with visually-hidden-focusable and an href pointing at the main content id, placed before the header. Use that class alone, never together with visually-hidden.
The Collapse plugin flips aria-expanded on the toggler for you. If the trigger is not a button, add role=”button”.
Inside a dropdown, an active entry takes aria-current=”true”, because it marks the current item in a set. Page-level links take “page”.
Bootstrap adds cursor-key movement and Esc to close on dropdowns, but no ARIA menu roles. Leave role=”menu” off unless you build the full pattern. An offcanvas panel needs aria-labelledby pointing at its title, and the script adds role=”dialog” itself.
Bootstrap’s components are generic on purpose, so authors often need to add further ARIA roles and attributes. The docs note where.
Text contrast is the last thing to check, meaning the contrast ratio between link text and its background. WCAG 2.2 sets 4.5:1 for normal text and 3:1 for large text, meaning 18 point or 14 point bold (W3C, WCAG 2.2).
Bootstrap’s own sources split on how safe the default palette is. The v5.0.0 migration notes say the framework raised its internal threshold from 3:1 to 4.5:1, yet the accessibility page still warns that some default color pairs fall below 4.5:1, especially on light backgrounds.
Test your pair either way. Disabled links are the one exception, since WCAG sets no contrast requirement for inactive components, and the default disabled color on dark navbars is white at .25 opacity.
The accessibility docs point to Color Contrast Analyser, HTML_CodeSniffer, Deque axe and Microsoft Accessibility Insights for testing. Run one on both the open and closed menu states.
When the Bootstrap Header Breaks
Most broken headers come down to markup written for a different version of Bootstrap. Script problems and layout side effects from scrolling or padding settings cover the rest.
Toggler and dropdown failures
When the toggler or a dropdown does nothing, check these first.
- The bundle script is missing, or both bootstrap.js and bootstrap.min.js load (the docs say not to include both).
- Version 4 attributes sit on a v5 page. Bootstrap 5 namespaced them as data-bs-*, so data-toggle and data-target do nothing.
- The snippet came from MDB, whose data-mdb-* attributes plain Bootstrap ignores.
- Two collapse wrappers share one id, and the selector finds only the first match.
React, Vue and Angular projects hit a separate problem. Bootstrap’s JavaScript is not fully compatible with them, and both sides may mutate the same element, leaving dropdowns stuck open (Bootstrap 5.3 JavaScript docs).
Keep the CSS and swap the scripts for React Bootstrap or ng-bootstrap. For Vue 3, the docs list BootstrapVueNext, which they mark as alpha as of October 2026.
Version mismatches
Bootstrap 4.6.2, published July 19, 2022, is the last release on the 4.x line (npm registry). Snippets written for it still turn up in header searches.
| Item | Bootstrap 4 | Bootstrap 5 |
|---|
| Toggler attributes | data-toggle, data-target | data-bs-toggle, data-bs-target |
| JavaScript dependency | jQuery, Popper 1.x | No jQuery, Popper 2.x in the bundle |
| Spacing classes | ml-auto, mr-auto | ms-auto, me-auto |
| Active class | On .nav-item or .nav-link | On .nav-link only |
| Inner container | Optional | Required inside the navbar |
The usual failure is a mix of columns, like a v4 toggler running on v5 scripts, or ml-auto on a v5 page where the margin does nothing.
Layout side effects
navbar-nav-scroll sets overflow-y: auto, which forces overflow-x to auto as well, so some horizontal content gets cropped (Bootstrap 5.3 navbar docs).
Padding on the .collapse element is a separate trap. The plugin animates height down to 0, so padding there cannot animate cleanly and the docs advise against it. Put the padding on an inner wrapper.
If your custom CSS loses to Bootstrap’s, load your stylesheet after Bootstrap’s and keep selectors specific. A guide to overriding Bootstrap’s default CSS covers the specificity rules.
Fix the version first. Everything else is smaller.
Bootstrap Header FAQ
How do I center the links in a Bootstrap header?
Add mx-auto to the navbar-nav list. The auto margins on both sides place the links in the free space between the brand and any buttons, which is not always the exact center of the page.
Can a Bootstrap header sit transparent over a hero image?
Yes. Add bg-transparent, then lift the navbar out of the flow with position-absolute and w-100, or fixed-top.
Set data-bs-theme=”dark” if the image is dark. The opened mobile menu still needs its own background to stay readable.
Why does the mobile menu stay open after a link click?
The Collapse plugin closes the menu only through its own toggler, and anchor links on a single page do not reload anything. Call hide() on the collapse instance from a click handler on the links. Bootstrap’s methods are asynchronous, so the menu finishes closing after the call returns.
Can the header highlight the current section while scrolling?
Yes, with the Scrollspy plugin. Set data-bs-spy=”scroll” on the scrolling element, point data-bs-target at the nav, and give each link an href that matches a section id.
Since v5.2.0 it uses the Intersection Observer API and no longer needs a relatively positioned parent (Bootstrap migration notes).
How do I change the Bootstrap header height?
The navbar has no fixed height, so padding sets it. Override –bs-navbar-padding-y on the .navbar, or add py-* utilities, and remember that brand size and link line height add to the result.
Does a Bootstrap header work with right-to-left languages?
Yes. Bootstrap 5 renamed directional classes to logical ones (ms-auto, me-auto, start, end), so the same markup mirrors correctly. Load the RTL build of the CSS and add dir=”rtl” to the html element.
Keeping a Bootstrap Header Consistent Through Upgrades
A Bootstrap header stays consistent across every page when one shared template renders it and the framework version is pinned to an exact release.
Start by moving the header markup into one shared partial, which turns a site-wide change into one edit instead of one per page. Pin the CDN path or npm version exactly after that. Replacing deprecated classes before the next minor release comes last.
Pinning carries a cost. The docs’ own CDN examples lock bootstrap@5.3.8 behind an integrity hash, so every patch release needs a manual version bump.
Bootstrap 6 is the next thing to plan around. As of October 2026, the 5.3 docs list v5.3.8 as current and schedule .text-muted for removal in v6.0.0, and v6.0.0-alpha.1 has been on npm since October 8, 2026, so audit deprecated classes before the stable release ships.