floatingConfig: null,
placement: DEFAULT_PLACEMENT,
reference: 'toggle',
+ strategy: 'absolute',
// Submenu options
submenuTrigger: 'both', // 'click', 'hover', or 'both'
submenuDelay: SUBMENU_CLOSE_DELAY
floatingConfig: '(null|object|function)',
placement: 'string',
reference: '(string|element|object)',
+ strategy: 'string',
submenuTrigger: 'string',
submenuDelay: 'number'
}
referenceElement,
this._menu,
floatingConfig.placement,
- floatingConfig.middleware
+ floatingConfig.middleware,
+ floatingConfig.strategy
)
}
_getFloatingConfig(placement, middleware) {
const defaultConfig = {
placement,
- middleware
+ middleware,
+ strategy: this._config.strategy
}
return {
}
// Shared helper for positioning any floating element
- async _applyFloatingPosition(reference, floating, placement, middleware) {
+ async _applyFloatingPosition(reference, floating, placement, middleware, strategy = 'absolute') {
if (!floating.isConnected) {
return null
}
const { x, y, placement: finalPlacement } = await computePosition(
reference,
floating,
- { placement, middleware }
+ { placement, middleware, strategy }
)
if (!floating.isConnected) {
}
Object.assign(floating.style, {
- position: 'absolute',
+ position: strategy,
left: `${x}px`,
top: `${y}px`,
margin: '0'
--- /dev/null
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap nav-overflow.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+import BaseComponent from './base-component.js'
+import EventHandler from './dom/event-handler.js'
+import SelectorEngine from './dom/selector-engine.js'
+import Dropdown from './dropdown.js'
+
+/**
+ * Constants
+ */
+
+const NAME = 'navoverflow'
+const DATA_KEY = 'bs.navoverflow'
+const EVENT_KEY = `.${DATA_KEY}`
+
+const EVENT_UPDATE = `update${EVENT_KEY}`
+const EVENT_OVERFLOW = `overflow${EVENT_KEY}`
+
+const CLASS_NAME_OVERFLOW = 'nav-overflow'
+const CLASS_NAME_OVERFLOW_MENU = 'nav-overflow-menu'
+const CLASS_NAME_HIDDEN = 'd-none'
+
+const SELECTOR_NAV_ITEM = '.nav-item'
+const SELECTOR_NAV_LINK = '.nav-link'
+const SELECTOR_OVERFLOW_TOGGLE = '.nav-overflow-toggle'
+const SELECTOR_OVERFLOW_MENU = '.nav-overflow-menu'
+const CLASS_NAME_KEEP = 'nav-overflow-keep'
+
+const Default = {
+ moreText: 'More',
+ moreIcon: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"><path d="M3 9.5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3m5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3m5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3"/></svg>',
+ threshold: 0 // Minimum items to keep visible before showing overflow
+}
+
+const DefaultType = {
+ moreText: 'string',
+ moreIcon: 'string',
+ threshold: 'number'
+}
+
+/**
+ * Class definition
+ */
+
+class NavOverflow extends BaseComponent {
+ constructor(element, config) {
+ super(element, config)
+
+ this._items = []
+ this._overflowItems = []
+ this._overflowMenu = null
+ this._overflowToggle = null
+ this._resizeObserver = null
+ this._isInitialized = false
+
+ this._init()
+ }
+
+ // Getters
+ static get Default() {
+ return Default
+ }
+
+ static get DefaultType() {
+ return DefaultType
+ }
+
+ static get NAME() {
+ return NAME
+ }
+
+ // Public
+ update() {
+ this._calculateOverflow()
+ EventHandler.trigger(this._element, EVENT_UPDATE)
+ }
+
+ dispose() {
+ if (this._resizeObserver) {
+ this._resizeObserver.disconnect()
+ }
+
+ // Move items back to original positions
+ this._restoreItems()
+
+ // Remove overflow menu
+ if (this._overflowToggle && this._overflowToggle.parentElement) {
+ this._overflowToggle.parentElement.remove()
+ }
+
+ super.dispose()
+ }
+
+ // Private
+ _init() {
+ // Add overflow class to nav
+ this._element.classList.add(CLASS_NAME_OVERFLOW)
+
+ // Get all nav items
+ this._items = [...SelectorEngine.find(SELECTOR_NAV_ITEM, this._element)]
+
+ // Store original order data
+ for (const [index, item] of this._items.entries()) {
+ item.dataset.bsNavOrder = index
+ }
+
+ // Create overflow dropdown if it doesn't exist
+ this._createOverflowMenu()
+
+ // Setup resize observer
+ this._setupResizeObserver()
+
+ // Initial calculation
+ this._calculateOverflow()
+
+ this._isInitialized = true
+ }
+
+ _createOverflowMenu() {
+ // Check if overflow menu already exists
+ this._overflowToggle = SelectorEngine.findOne(SELECTOR_OVERFLOW_TOGGLE, this._element)
+
+ if (this._overflowToggle) {
+ this._overflowMenu = SelectorEngine.findOne(SELECTOR_OVERFLOW_MENU, this._element)
+ return
+ }
+
+ // Create the overflow dropdown item
+ const overflowItem = document.createElement('li')
+ overflowItem.className = 'nav-item nav-overflow-item dropdown'
+ overflowItem.innerHTML = `
+ <button class="nav-link nav-overflow-toggle dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
+ <span class="nav-overflow-icon">${this._config.moreIcon}</span>
+ <span class="nav-overflow-text">${this._config.moreText}</span>
+ </button>
+ <ul class="${CLASS_NAME_OVERFLOW_MENU} dropdown-menu dropdown-menu-end"></ul>
+ `
+
+ this._element.append(overflowItem)
+ this._overflowToggle = overflowItem.querySelector(SELECTOR_OVERFLOW_TOGGLE)
+ this._overflowMenu = overflowItem.querySelector(SELECTOR_OVERFLOW_MENU)
+
+ // Initialize dropdown with fixed strategy to escape overflow containers
+ Dropdown.getOrCreateInstance(this._overflowToggle, {
+ strategy: 'fixed'
+ })
+ }
+
+ _setupResizeObserver() {
+ if (typeof ResizeObserver === 'undefined') {
+ // Fallback for older browsers
+ EventHandler.on(window, 'resize', () => this._calculateOverflow())
+ return
+ }
+
+ this._resizeObserver = new ResizeObserver(() => {
+ this._calculateOverflow()
+ })
+
+ this._resizeObserver.observe(this._element)
+ }
+
+ _calculateOverflow() {
+ // First, restore all items to measure properly
+ this._restoreItems()
+
+ const navWidth = this._element.offsetWidth
+ const overflowItem = this._overflowToggle?.closest('.nav-item')
+ const overflowWidth = overflowItem?.offsetWidth || 0
+
+ let usedWidth = 0
+ const itemsToOverflow = []
+ const overflowThreshold = navWidth - overflowWidth - 10 // 10px buffer
+
+ // Calculate which items need to overflow (skip items with keep class)
+ for (const item of this._items) {
+ const itemWidth = item.offsetWidth
+ usedWidth += itemWidth
+
+ // Never overflow items with the keep class
+ if (item.classList.contains(CLASS_NAME_KEEP)) {
+ continue
+ }
+
+ if (usedWidth > overflowThreshold) {
+ itemsToOverflow.push(item)
+ }
+ }
+
+ // Check if we need threshold minimum visible
+ const visibleCount = this._items.length - itemsToOverflow.length
+ if (visibleCount < this._config.threshold && this._items.length > this._config.threshold) {
+ // Add more items to overflow until we reach threshold (but not keep items)
+ const toMove = this._items.slice(this._config.threshold).filter(item => !item.classList.contains(CLASS_NAME_KEEP))
+ itemsToOverflow.length = 0
+ itemsToOverflow.push(...toMove)
+ }
+
+ // Move items to overflow menu
+ this._moveToOverflow(itemsToOverflow)
+
+ // Show/hide overflow toggle
+ if (overflowItem) {
+ if (itemsToOverflow.length > 0) {
+ overflowItem.classList.remove(CLASS_NAME_HIDDEN)
+ } else {
+ overflowItem.classList.add(CLASS_NAME_HIDDEN)
+ }
+ }
+
+ // Trigger overflow event if items changed
+ if (itemsToOverflow.length > 0) {
+ EventHandler.trigger(this._element, EVENT_OVERFLOW, {
+ overflowCount: itemsToOverflow.length,
+ visibleCount: this._items.length - itemsToOverflow.length
+ })
+ }
+ }
+
+ _moveToOverflow(items) {
+ if (!this._overflowMenu) {
+ return
+ }
+
+ // Clear existing overflow items
+ this._overflowMenu.innerHTML = ''
+ this._overflowItems = []
+
+ for (const item of items) {
+ // Clone the nav link as a dropdown item
+ const link = SelectorEngine.findOne(SELECTOR_NAV_LINK, item)
+ if (!link) {
+ continue
+ }
+
+ const dropdownItem = document.createElement('li')
+ const clonedLink = link.cloneNode(true)
+ clonedLink.className = 'dropdown-item'
+
+ // Preserve active state
+ if (link.classList.contains('active')) {
+ clonedLink.classList.add('active')
+ }
+
+ // Preserve disabled state
+ if (link.classList.contains('disabled') || link.hasAttribute('disabled')) {
+ clonedLink.classList.add('disabled')
+ }
+
+ dropdownItem.append(clonedLink)
+ this._overflowMenu.append(dropdownItem)
+
+ // Hide original item
+ item.classList.add(CLASS_NAME_HIDDEN)
+ item.dataset.bsNavOverflow = 'true'
+
+ this._overflowItems.push(item)
+ }
+ }
+
+ _restoreItems() {
+ for (const item of this._items) {
+ item.classList.remove(CLASS_NAME_HIDDEN)
+ delete item.dataset.bsNavOverflow
+ }
+
+ if (this._overflowMenu) {
+ this._overflowMenu.innerHTML = ''
+ }
+
+ this._overflowItems = []
+ }
+}
+
+/**
+ * Data API implementation
+ */
+
+EventHandler.on(document, 'DOMContentLoaded', () => {
+ for (const element of SelectorEngine.find('[data-bs-toggle="nav-overflow"]')) {
+ NavOverflow.getOrCreateInstance(element)
+ }
+})
+
+export default NavOverflow
--- /dev/null
+// Nav Overflow (Priority+ Pattern)
+//
+// A responsive navigation pattern that automatically moves items
+// to an overflow dropdown when space is limited.
+
+@use "config" as *;
+@use "variables" as *;
+
+@layer components {
+ .nav-overflow {
+ flex-wrap: nowrap;
+ }
+
+ // Container item for overflow
+ .nav-overflow-item {
+ flex-shrink: 0;
+ margin-inline-start: auto;
+ }
+
+ // Hide items that have been moved to overflow
+ .nav-overflow [data-bs-nav-overflow="true"] {
+ display: none;
+ }
+
+ // Preserve items that should never overflow
+ .nav-overflow-keep {
+ flex-shrink: 0;
+ }
+}
$nav-link-gap: .5rem !default;
$nav-link-align: center !default;
$nav-link-justify: center !default;
-$nav-link-padding-y: .5rem !default;
-$nav-link-padding-x: 1rem !default;
+$nav-link-padding-y: .375rem !default;
+$nav-link-padding-x: .75rem !default;
$nav-link-color: var(--fg-2) !default;
$nav-link-hover-color: var(--fg-1) !default;
$nav-link-hover-bg: var(--bg-1) !default;
font-weight: var(--nav-link-font-weight);
color: var(--nav-link-color);
text-decoration: none;
+ white-space: nowrap;
background: none;
border: 0;
@include border-radius(var(--border-radius));
@use "mixins/transition" as *;
// scss-docs-start navbar-variables
-$navbar-padding-y: $spacer * .5 !default;
+$navbar-padding-y: $spacer * .25 !default;
$navbar-padding-x: null !default;
$navbar-nav-link-padding-x: .75rem !default;
$navbar-brand-font-size: $font-size-lg !default;
-// Compute the navbar-brand padding-y so the navbar-brand will have the same height as navbar-text and nav-link
-// mdo-do: fix this
-// $nav-link-height: $font-size-base * $line-height-base + $nav-link-padding-y * 2 !default;
-// $navbar-brand-height: $navbar-brand-font-size * $line-height-base !default;
$navbar-brand-height: 1.5rem !default;
-// $navbar-brand-padding-y: ($nav-link-height - $navbar-brand-height) * .5 !default;
$navbar-brand-padding-y: $navbar-brand-height * .5 !default;
$navbar-brand-margin-end: 1rem !default;
-$navbar-toggler-padding-y: .25rem !default;
-$navbar-toggler-padding-x: .75rem !default;
+$navbar-toggler-padding-y: .375rem !default;
+$navbar-toggler-padding-x: .375rem !default;
$navbar-toggler-font-size: $font-size-lg !default;
$navbar-toggler-border-radius: var(--border-radius) !default;
$navbar-toggler-transition: box-shadow .15s ease-in-out !default;
$navbar-light-hover-color: var(--fg-1) !default;
$navbar-light-active-color: var(--fg) !default;
$navbar-light-disabled-color: var(--fg-3) !default;
-$navbar-light-icon-color: color-mix(in oklch, var(--body-color) 75%, transparent) !default;
-$navbar-light-toggler-icon-bg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'><path stroke='#{$navbar-light-icon-color}' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/></svg>") !default;
$navbar-light-toggler-border-color: color-mix(in oklch, var(--fg-body) 15%, transparent) !default;
$navbar-light-brand-color: $navbar-light-active-color !default;
$navbar-light-brand-hover-color: $navbar-light-active-color !default;
$navbar-dark-hover-color: rgba($white, .75) !default;
$navbar-dark-active-color: $white !default;
$navbar-dark-disabled-color: rgba($white, .25) !default;
-$navbar-dark-icon-color: $navbar-dark-color !default;
-$navbar-dark-toggler-icon-bg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'><path stroke='#{$navbar-dark-icon-color}' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/></svg>") !default;
$navbar-dark-toggler-border-color: rgba($white, .1) !default;
$navbar-dark-brand-color: $navbar-dark-active-color !default;
$navbar-dark-brand-hover-color: $navbar-dark-active-color !default;
// scss-docs-end navbar-dark-variables
@layer components {
+ // Base navbar
.navbar {
// scss-docs-start navbar-css-vars
// stylelint-disable-next-line scss/at-function-named-arguments
--navbar-toggler-padding-y: #{$navbar-toggler-padding-y};
--navbar-toggler-padding-x: #{$navbar-toggler-padding-x};
--navbar-toggler-font-size: #{$navbar-toggler-font-size};
- --navbar-toggler-icon-bg: #{escape-svg($navbar-light-toggler-icon-bg)};
--navbar-toggler-border-color: #{$navbar-light-toggler-border-color};
--navbar-toggler-border-radius: #{$navbar-toggler-border-radius};
--navbar-toggler-transition: #{$navbar-toggler-transition};
position: relative;
display: flex;
- flex-wrap: wrap; // allow us to do the line break for collapsing content
+ flex-wrap: wrap;
align-items: center;
- justify-content: space-between; // space out brand from logo
+ justify-content: space-between;
padding: var(--navbar-padding-y) var(--navbar-padding-x);
+ container-type: inline-size; // Enable container queries for responsive behavior
@include gradient-bg();
- // Because flex properties aren't inherited, we need to redeclare these first
- // few properties so that content nested within behave properly.
- // The `flex-wrap` property is inherited to simplify the expanded navbars
+ // Container properties for nested containers
%container-flex-properties {
display: flex;
flex-wrap: inherit;
// Navbar nav
//
- // Custom navbar navigation (doesn't require `.nav`, but does make use of `.nav-link`).
+ // Navigation within navbars. Sets all nav-link CSS variables needed for
+ // proper styling. Can be used standalone or with `.nav` base class.
.navbar-nav {
// scss-docs-start navbar-nav-css-vars
- // --nav-link-padding-x: 0;
- // @mdo-do: fix this, navbar shouldn't need to reuse nav link variables mb? or we need to bring them in…
- // --nav-link-padding-y: #{$nav-link-padding-y};
- // @include rfs($nav-link-font-size, --nav-link-font-size);
- // --nav-link-font-weight: #{$nav-link-font-weight};
+ // Set all nav-link variables for self-contained styling
+ --nav-gap: .25rem;
+ --nav-link-gap: .5rem;
+ --nav-link-padding-x: .5rem;
+ --nav-link-padding-y: .5rem;
--nav-link-color: var(--navbar-color);
--nav-link-hover-color: var(--navbar-hover-color);
+ --nav-link-hover-bg: transparent;
+ --nav-link-active-color: var(--navbar-active-color);
+ --nav-link-active-bg: transparent;
--nav-link-disabled-color: var(--navbar-disabled-color);
// scss-docs-end navbar-nav-css-vars
display: flex;
- flex-direction: column; // cannot use `inherit` to get the `.navbar`s value
+ flex-direction: column;
+ gap: var(--nav-gap);
padding-inline-start: 0;
margin-bottom: 0;
list-style: none;
.nav-link {
+ white-space: nowrap;
+
&.active,
&.show {
color: var(--navbar-active-color);
}
}
-
- // .dropdown-menu {
- // position: static;
- // }
}
// Navbar text
//
- //
+ // For adding text or inline elements to the navbar
.navbar-text {
- // @mdo-do: fix this too
- // padding-top: $nav-link-padding-y;
- // padding-bottom: $nav-link-padding-y;
+ padding-top: var(--navbar-brand-padding-y);
+ padding-bottom: var(--navbar-brand-padding-y);
color: var(--navbar-color);
a,
a:hover,
- a:focus {
+ a:focus {
color: var(--navbar-active-color);
}
}
- // Responsive navbar
+ // Navbar toggler
//
- // Custom styles for responsive collapsing and toggling of navbar contents.
- // Powered by the collapse Bootstrap JavaScript plugin.
-
- // When collapsed, prevent the toggleable navbar contents from appearing in
- // the default flexbox row orientation. Requires the use of `flex-wrap: wrap`
- // on the `.navbar` parent.
- .navbar-collapse {
- flex-grow: 1;
- flex-basis: 100%;
- // For always expanded or extra full navbars, ensure content aligns itself
- // properly vertically. Can be easily overridden with flex utilities.
- align-items: center;
- }
-
// Button for toggling the navbar when in its collapsed state
+
.navbar-toggler {
padding: var(--navbar-toggler-padding-y) var(--navbar-toggler-padding-x);
font-size: var(--navbar-toggler-font-size);
line-height: 1;
color: var(--navbar-color);
- background-color: transparent; // remove default button style
- border: var(--border-width) solid var(--navbar-toggler-border-color); // remove default button style
+ background-color: transparent;
+ border: var(--border-width) solid var(--navbar-toggler-border-color);
@include border-radius(var(--navbar-toggler-border-radius));
@include transition(var(--navbar-toggler-transition));
}
}
- // Keep as a separate element so folks can easily override it with another icon
- // or image file as needed.
+ // Navbar toggler icon (inline SVG)
.navbar-toggler-icon {
display: inline-block;
- width: 1.5em;
- height: 1.5em;
- vertical-align: middle;
- background-image: var(--navbar-toggler-icon-bg);
- background-repeat: no-repeat;
- background-position: center;
- background-size: 100%;
+ width: 1em;
+ height: 1em;
+ color: var(--navbar-color);
+ vertical-align: -.125em;
}
- .navbar-nav-scroll {
- max-height: var(--scroll-height, 75vh);
- overflow-y: auto;
- }
// scss-docs-start navbar-expand-loop
// Generate series of `.navbar-expand-*` responsive classes for configuring
- // where your navbar collapses.
+ // where your navbar collapses and expands. Uses container queries so the
+ // navbar responds to its own width, not the viewport width.
+
+ // Mixin for expanded state styles (applied to descendants)
+ @mixin navbar-expanded {
+ // Style the inner container since we can't style .navbar itself with container queries
+ > .container,
+ > .container-fluid,
+ %navbar-expand-container {
+ flex-wrap: nowrap;
+ justify-content: flex-start;
+ }
+
+ .navbar-nav {
+ --nav-link-padding-x: var(--navbar-nav-link-padding-x);
+ flex-direction: row;
+ }
+
+ .navbar-toggler {
+ display: none !important; // stylelint-disable-line declaration-no-important
+ }
+
+ .offcanvas {
+ // stylelint-disable declaration-no-important
+ position: static;
+ z-index: auto;
+ flex-grow: 1;
+ width: auto !important;
+ height: auto !important;
+ visibility: visible !important;
+ background-color: transparent !important;
+ border: 0 !important;
+ transform: none !important;
+ @include box-shadow(none);
+ @include transition(none);
+ // stylelint-enable declaration-no-important
+
+ .offcanvas-header {
+ display: none;
+ }
+
+ .offcanvas-body {
+ display: flex;
+ flex-grow: 0;
+ align-items: center;
+ padding: 0;
+ overflow-y: visible;
+ }
+ }
+ }
+
+ // Always expanded (no responsive behavior)
.navbar-expand {
- @each $breakpoint in map.keys($grid-breakpoints) {
- $next: breakpoint-next($breakpoint, $grid-breakpoints);
- $infix: breakpoint-infix($next, $grid-breakpoints);
-
- // stylelint-disable-next-line scss/selector-no-union-class-name
- &#{$infix} {
- @include media-breakpoint-up($next) {
- flex-wrap: nowrap;
- justify-content: flex-start;
-
- .navbar-nav {
- --nav-link-padding-x: var(--navbar-nav-link-padding-x);
- flex-direction: row;
-
- // .dropdown-menu {
- // position: absolute;
- // }
-
- // .nav-link {
- // padding-inline: var(--navbar-nav-link-padding-x);
- // }
- }
-
- .navbar-nav-scroll {
- overflow: visible;
- }
-
- .navbar-collapse {
- display: flex !important; // stylelint-disable-line declaration-no-important
- flex-basis: auto;
- }
-
- .navbar-toggler {
- display: none !important; // stylelint-disable-line declaration-no-important
- }
-
- .offcanvas {
- // stylelint-disable declaration-no-important
- position: static;
- z-index: auto;
- flex-grow: 1;
- width: auto !important;
- height: auto !important;
- visibility: visible !important;
- background-color: transparent !important;
- border: 0 !important;
- transform: none !important;
- @include box-shadow(none);
- @include transition(none);
- // stylelint-enable declaration-no-important
-
- .offcanvas-header {
- display: none;
- }
-
- .offcanvas-body {
- display: flex;
- flex-grow: 0;
- padding: 0;
- overflow-y: visible;
- }
- }
+ @include navbar-expanded();
+
+ // Also set on navbar itself for non-responsive case
+ flex-wrap: nowrap;
+ justify-content: flex-start;
+ }
+
+ // Responsive navbar expand classes using container queries
+ @each $breakpoint in map.keys($grid-breakpoints) {
+ $next: breakpoint-next($breakpoint, $grid-breakpoints);
+ $infix: breakpoint-infix($next, $grid-breakpoints);
+ $min-width: breakpoint-min($next, $grid-breakpoints);
+
+ @if $next and $min-width {
+ .navbar-expand#{$infix} {
+ @container (min-width: #{$min-width}) {
+ @include navbar-expanded();
}
}
}
}
// scss-docs-end navbar-expand-loop
+
// Navbar themes
//
- // Styles for switching between navbars with light or dark background.
+ // Style for dark navbar backgrounds. Use data-bs-theme="dark" for modern approach.
- .navbar-dark,
.navbar[data-bs-theme="dark"] {
// scss-docs-start navbar-dark-css-vars
--navbar-color: #{$navbar-dark-color};
--navbar-brand-color: #{$navbar-dark-brand-color};
--navbar-brand-hover-color: #{$navbar-dark-brand-hover-color};
--navbar-toggler-border-color: #{$navbar-dark-toggler-border-color};
- --navbar-toggler-icon-bg: #{escape-svg($navbar-dark-toggler-icon-bg)};
// scss-docs-end navbar-dark-css-vars
}
-
- @if $enable-dark-mode {
- @include color-mode(dark) {
- .navbar-toggler-icon {
- --navbar-toggler-icon-bg: #{escape-svg($navbar-dark-toggler-icon-bg)};
- }
- }
- }
}
@use "mixins/backdrop" as *;
@use "layout/breakpoints" as *;
+// scss-docs-start offcanvas-variables
+$offcanvas-padding-y: $spacer !default;
+$offcanvas-padding-x: $spacer !default;
+$offcanvas-horizontal-width: 400px !default;
+$offcanvas-vertical-height: 30vh !default;
+$offcanvas-transition-duration: .3s !default;
+$offcanvas-border-color: var(--border-color-translucent) !default;
+$offcanvas-border-width: var(--border-width) !default;
+$offcanvas-title-line-height: $line-height-base !default;
+$offcanvas-bg-color: var(--bg-body) !default;
+$offcanvas-color: var(--fg-body) !default;
+$offcanvas-box-shadow: var(--box-shadow-lg) !default;
+$offcanvas-backdrop-bg: $black !default;
+$offcanvas-backdrop-opacity: .5 !default;
+// scss-docs-end offcanvas-variables
+
%offcanvas-css-vars {
// scss-docs-start offcanvas-css-vars
--offcanvas-zindex: #{$zindex-offcanvas};
}
@layer components {
+ // Apply CSS vars to all offcanvas responsive variants
@each $breakpoint in map.keys($grid-breakpoints) {
$next: breakpoint-next($breakpoint, $grid-breakpoints);
$infix: breakpoint-infix($next, $grid-breakpoints);
}
}
+ // Responsive offcanvas styles
@each $breakpoint in map.keys($grid-breakpoints) {
$next: breakpoint-next($breakpoint, $grid-breakpoints);
$infix: breakpoint-infix($next, $grid-breakpoints);
@include box-shadow(var(--offcanvas-box-shadow));
@include transition(var(--offcanvas-transition));
+ // Placement: Start (left in LTR, right in RTL)
&.offcanvas-start {
inset-block: 0;
inset-inline-start: 0;
}
}
+ // Placement: End (right in LTR, left in RTL)
&.offcanvas-end {
inset-block: 0;
inset-inline-end: 0;
}
}
+ // Placement: Top
&.offcanvas-top {
inset: 0 0 auto;
height: var(--offcanvas-height);
transform: translateY(-100%);
}
+ // Placement: Bottom
&.offcanvas-bottom {
inset: auto 0 0;
height: var(--offcanvas-height);
transform: translateY(100%);
}
+ // Fullscreen variant - covers entire viewport
+ &.offcanvas-fullscreen {
+ inset: 0;
+ width: 100%;
+ max-width: none;
+ height: 100%;
+ max-height: none;
+ border: 0;
+ transform: translateY(100%);
+ }
+
+ // Show/hide states
&.showing,
&.show:not(.hiding) {
transform: none;
}
}
+ // Above breakpoint - show content inline (for responsive offcanvas)
@if not ($infix == "") {
@include media-breakpoint-up($next) {
--offcanvas-height: auto;
flex-grow: 0;
padding: 0;
overflow-y: visible;
- // Reset `background-color` in case `.bg-*` classes are used in offcanvas
background-color: transparent !important; // stylelint-disable-line declaration-no-important
}
}
}
}
+ // Backdrop overlay
.offcanvas-backdrop {
@include overlay-backdrop($zindex-offcanvas-backdrop, $offcanvas-backdrop-bg, $offcanvas-backdrop-opacity);
}
+ // Header with close button
.offcanvas-header {
display: flex;
align-items: center;
.btn-close {
padding: calc(var(--offcanvas-padding-y) * .5) calc(var(--offcanvas-padding-x) * .5);
- // Split properties to avoid invalid calc() function if value is 0
margin-inline-start: auto;
margin-inline-end: calc(-.5 * var(--offcanvas-padding-x));
margin-top: calc(-.5 * var(--offcanvas-padding-y));
}
}
+ // Title
.offcanvas-title {
margin-bottom: 0;
line-height: var(--offcanvas-title-line-height);
}
+ // Scrollable body
.offcanvas-body {
flex-grow: 1;
padding: var(--offcanvas-padding-y) var(--offcanvas-padding-x);
overflow-y: auto;
}
+
+ // Optional footer
+ .offcanvas-footer {
+ display: flex;
+ flex-shrink: 0;
+ flex-wrap: wrap;
+ gap: .5rem;
+ align-items: center;
+ justify-content: flex-end;
+ padding: var(--offcanvas-padding-y) var(--offcanvas-padding-x);
+ border-block-start: var(--offcanvas-border-width) solid var(--offcanvas-border-color);
+ }
}
@forward "dropdown";
@forward "list-group";
@forward "nav";
+@forward "nav-overflow";
@forward "navbar";
@forward "offcanvas";
@forward "pagination";
- title: Dialog
- title: Dropdown
- title: List group
- - title: Navbar
- title: Navs & tabs
+ - title: Nav overflow
+ - title: Navbar
- title: Offcanvas
- title: Pagination
- title: Placeholder
<strong>الألبوم</strong>
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarHeader" aria-controls="navbarHeader" aria-expanded="false" aria-label="تبديل التنقل">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
</div>
</div>
<strong>Album</strong>
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarHeader" aria-controls="navbarHeader" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
</div>
</div>
<div class="container-fluid">
<a class="navbar-brand" href="#">شرائح العرض</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="تبديل التنقل">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav me-auto mb-2 mb-md-0">
<div class="container-fluid">
<a class="navbar-brand" href="#">Carousel</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav me-auto mb-2 mb-md-0">
<img src="${getVersionedDocsPath('/assets/brand/bootstrap-logo-white.svg')}" width="38" height="30" class="d-inline-block align-top" alt="Bootstrap" loading="lazy" style="filter: invert(1) grayscale(100%) brightness(200%);">
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="تبديل التنقل">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<img src="${getVersionedDocsPath('/assets/brand/bootstrap-logo-white.svg')}" width="38" height="30" class="d-inline-block align-top" alt="Bootstrap" loading="lazy">
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent2" aria-controls="navbarSupportedContent2" aria-expanded="false" aria-label="تبديل التنقل">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent2">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<img src="${getVersionedDocsPath('/assets/brand/bootstrap-logo-white.svg')}" width="38" height="30" class="d-inline-block align-top" alt="Bootstrap" loading="lazy" style="filter: invert(1) grayscale(100%) brightness(200%);">
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<img src="${getVersionedDocsPath('/assets/brand/bootstrap-logo-white.svg')}" width="38" height="30" class="d-inline-block align-top" alt="Bootstrap" loading="lazy">
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent2" aria-controls="navbarSupportedContent2" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent2">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<div class="container-fluid">
<a class="navbar-brand" href="#">Bottom navbar</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav">
<div class="container-fluid">
<a class="navbar-brand" href="#">Fixed navbar</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav me-auto mb-2 mb-md-0">
<div class="container-fluid">
<a class="navbar-brand" href="#">Top navbar</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav me-auto mb-2 mb-md-0">
<div class="container-fluid">
<a class="navbar-brand" href="#">Dark offcanvas navbar</a>
<button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasNavbarDark" aria-controls="offcanvasNavbarDark" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="offcanvas offcanvas-end text-bg-dark" tabindex="-1" id="offcanvasNavbarDark" aria-labelledby="offcanvasNavbarDarkLabel">
<div class="offcanvas-header">
<div class="container-fluid">
<a class="navbar-brand" href="#">Light offcanvas navbar</a>
<button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasNavbarLight" aria-controls="offcanvasNavbarLight" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasNavbarLight" aria-labelledby="offcanvasNavbarLightLabel">
<div class="offcanvas-header">
<div class="container-fluid">
<a class="navbar-brand" href="#">Responsive offcanvas navbar</a>
<button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasNavbar2" aria-controls="offcanvasNavbar2" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="offcanvas offcanvas-end text-bg-dark" tabindex="-1" id="offcanvasNavbar2" aria-labelledby="offcanvasNavbar2Label">
<div class="offcanvas-header">
<div class="container-fluid">
<a class="navbar-brand" href="#">Never expand</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample01" aria-controls="navbarsExample01" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="collapse navbar-collapse" id="navbarsExample01">
<div class="container-fluid">
<a class="navbar-brand" href="#">Always expand</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample02" aria-controls="navbarsExample02" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="collapse navbar-collapse" id="navbarsExample02">
<div class="container-fluid">
<a class="navbar-brand" href="#">Expand at sm</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample03" aria-controls="navbarsExample03" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="collapse navbar-collapse" id="navbarsExample03">
<div class="container-fluid">
<a class="navbar-brand" href="#">Expand at md</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample04" aria-controls="navbarsExample04" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="collapse navbar-collapse" id="navbarsExample04">
<div class="container-fluid">
<a class="navbar-brand" href="#">Expand at lg</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample05" aria-controls="navbarsExample05" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="collapse navbar-collapse" id="navbarsExample05">
<div class="container-fluid">
<a class="navbar-brand" href="#">Expand at xl</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample06" aria-controls="navbarsExample06" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="collapse navbar-collapse" id="navbarsExample06">
<div class="container-fluid">
<a class="navbar-brand" href="#">Expand at 2xl</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample2xl" aria-controls="navbarsExample2xl" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="collapse navbar-collapse" id="navbarsExample2xl">
<div class="container">
<a class="navbar-brand" href="#">Container</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample07" aria-controls="navbarsExample07" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="collapse navbar-collapse" id="navbarsExample07">
<div class="container-xl">
<a class="navbar-brand" href="#">Container XL</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample07XL" aria-controls="navbarsExample07XL" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="collapse navbar-collapse" id="navbarsExample07XL">
<nav class="navbar navbar-expand-lg navbar-dark bg-dark" aria-label="Tenth navbar example">
<div class="container-fluid">
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample08" aria-controls="navbarsExample08" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="collapse navbar-collapse justify-content-md-center" id="navbarsExample08">
<div class="container-fluid">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample09" aria-controls="navbarsExample09" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="collapse navbar-collapse" id="navbarsExample09">
<nav class="navbar navbar-expand-lg bg-body-tertiary rounded" aria-label="Twelfth navbar example">
<div class="container-fluid">
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample10" aria-controls="navbarsExample10" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="collapse navbar-collapse justify-content-md-center" id="navbarsExample10">
<nav class="navbar navbar-expand-lg bg-body-tertiary rounded" aria-label="Thirteenth navbar example">
<div class="container-fluid">
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample11" aria-controls="navbarsExample11" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="collapse navbar-collapse d-lg-flex" id="navbarsExample11">
<div class="container-fluid">
<a class="navbar-brand" href="#">Offcanvas navbar</a>
<button class="navbar-toggler p-0 border-0" type="button" id="navbarSideCollapse" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="navbar-collapse offcanvas-collapse" id="navbarsExampleDefault">
Aperture
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvas" aria-controls="offcanvas" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvas" aria-labelledby="offcanvasLabel">
<div class="offcanvas-header">
<div class="container-fluid">
<a class="navbar-brand" href="#">Fixed navbar</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav me-auto mb-2 mb-md-0">
<header class="navbar navbar-expand-lg bg-body bd-navbar border-bottom sticky-top bd-sticky-navbar">
<nav class="container-2xl bd-gutter flex-wrap flex-lg-nowrap" aria-label="Main navigation">
+ {/* Docs sidebar toggle - only shown on docs pages */}
{
layout === 'docs' && (
<div class="bd-navbar-toggle">
}
{layout !== 'docs' && <div class="d-lg-none" style="width: 4.25rem;" />}
+ {/* Brand */}
<a class="navbar-brand p-0 me-0 me-lg-2" href="/" aria-label="Bootstrap" style="color: var(--bs-indigo-500);">
<BootstrapWhiteFillIcon class="d-block my-1" height={32} width={40} />
</a>
+ {/* Search and main nav toggle */}
<div class="d-flex">
<div class="bd-search" id="docsearch" data-bd-docs-version={getConfig().docs_version}></div>
</button>
</div>
+ {/* Main navigation - offcanvas on mobile, inline on desktop */}
<div
class="offcanvas-lg offcanvas-end flex-grow-1"
tabindex="-1"
<OpenCollectiveIcon class="navbar-nav-svg" height={16} width={16} />
<small class="d-lg-none ms-2">Open Collective</small>
</LinkItem>
+
<li class="nav-item py-2 py-lg-1 col-12 col-lg-auto">
<div class="vr d-none d-lg-flex mx-lg-2 my-auto"></div>
<hr class="d-lg-none my-2" />
--- /dev/null
+---
+import Example from '@components/shortcodes/Example.astro'
+
+const placements = [
+ { value: '', label: 'Default (static)' },
+ { value: 'fixed-top', label: 'Fixed top' },
+ { value: 'fixed-bottom', label: 'Fixed bottom' },
+ { value: 'sticky-top', label: 'Sticky top' },
+ { value: 'sticky-bottom', label: 'Sticky bottom' }
+]
+---
+
+<div class="bg-1 p-3 fs-sm rounded-3">
+ <div class="vstack gap-1">
+ <label class="form-label fw-semibold mb-0">Placement</label>
+ <div class="dropdown">
+ <button
+ type="button"
+ class="btn btn-outline theme-secondary dropdown-toggle"
+ id="navbar-placement-dropdown"
+ data-bs-toggle="dropdown"
+ aria-expanded="false"
+ data-placement=""
+ >
+ <span>Default (static)</span>
+ <svg class="bi ms-1" width="16" height="16" aria-hidden="true">
+ <use href="#chevron-expand" />
+ </svg>
+ </button>
+ <ul class="dropdown-menu" aria-labelledby="navbar-placement-dropdown">
+ {placements.map((p) => (
+ <li>
+ <a
+ class:list={['dropdown-item', { 'active': p.value === '' }]}
+ href="#"
+ data-placement={p.value}
+ >
+ {p.label}
+ </a>
+ </li>
+ ))}
+ </ul>
+ </div>
+ </div>
+</div>
+
+<Example
+ code={`<nav class="navbar bg-1">
+ <div class="container-fluid">
+ <a class="navbar-brand" href="#">Default</a>
+ </div>
+</nav>`}
+ id="navbar-placement-preview"
+/>
+
+<script>
+ const placementDropdownButton = document.querySelector('#navbar-placement-dropdown') as HTMLButtonElement
+ const placementDropdownItems = document.querySelectorAll('#navbar-placement-dropdown + .dropdown-menu .dropdown-item')
+ const previewContainer = document.querySelector('#navbar-placement-preview') as HTMLElement
+ const previewNavbar = previewContainer?.querySelector('.navbar') as HTMLElement
+ const codeSnippet = previewContainer?.closest('.bd-example-snippet')?.querySelector('.highlight code') as HTMLElement
+
+ const placementClasses = ['fixed-top', 'fixed-bottom', 'sticky-top', 'sticky-bottom']
+
+ const placementLabels: Record<string, string> = {
+ '': 'Default',
+ 'fixed-top': 'Fixed top',
+ 'fixed-bottom': 'Fixed bottom',
+ 'sticky-top': 'Sticky top',
+ 'sticky-bottom': 'Sticky bottom'
+ }
+
+ function updatePlacement(placement: string) {
+ if (!previewNavbar || !placementDropdownButton) return
+
+ // Update dropdown button text
+ const labelSpan = placementDropdownButton.querySelector('span')
+ if (labelSpan) {
+ labelSpan.textContent = placementLabels[placement] ? `${placementLabels[placement]}${placement ? '' : ' (static)'}` : 'Default (static)'
+ }
+ placementDropdownButton.dataset.placement = placement
+
+ // Update active state in dropdown
+ placementDropdownItems.forEach(item => {
+ const itemPlacement = (item as HTMLElement).dataset.placement
+ item.classList.toggle('active', itemPlacement === placement)
+ })
+
+ // Remove all placement classes
+ placementClasses.forEach(cls => {
+ previewNavbar.classList.remove(cls)
+ })
+
+ // Add new placement class if not default
+ if (placement) {
+ previewNavbar.classList.add(placement)
+ }
+
+ // Update the brand text to show current placement
+ const brand = previewNavbar.querySelector('.navbar-brand')
+ if (brand) {
+ brand.textContent = placementLabels[placement] || 'Default'
+ }
+
+ // Update code snippet
+ updateCodeSnippet(placement)
+ }
+
+ function updateCodeSnippet(placement: string) {
+ if (!codeSnippet) return
+
+ const placementClass = placement ? ` ${placement}` : ''
+ const label = placementLabels[placement] || 'Default'
+
+ const htmlCode = `<nav class="navbar${placementClass} bg-body-tertiary">
+ <div class="container-fluid">
+ <a class="navbar-brand" href="#">${label}</a>
+ </div>
+</nav>`
+
+ codeSnippet.className = 'language-html'
+ codeSnippet.textContent = htmlCode
+
+ if (typeof window !== 'undefined' && (window as any).Prism) {
+ (window as any).Prism.highlightElement(codeSnippet)
+ }
+ }
+
+ // Initialize dropdown
+ if (placementDropdownButton) {
+ const placementDropdown = bootstrap.Dropdown.getOrCreateInstance(placementDropdownButton)
+
+ placementDropdownItems.forEach(item => {
+ item.addEventListener('click', (e) => {
+ e.preventDefault()
+ const placement = (item as HTMLElement).dataset.placement || ''
+ updatePlacement(placement)
+ placementDropdown.hide()
+ })
+ })
+ }
+</script>
--- /dev/null
+---
+import { replacePlaceholdersInHtml } from '@libs/placeholder'
+import Code from '@components/shortcodes/Code.astro'
+
+interface Props {
+ /**
+ * The example code.
+ */
+ code: string | string[]
+ /**
+ * The CSS class(es) to be added to the resizable container.
+ */
+ class?: string
+ /**
+ * Alias for class prop.
+ */
+ className?: string
+ /**
+ * Initial width of the resizable container.
+ * @default '100%'
+ */
+ initialWidth?: string
+ /**
+ * Minimum width of the resizable container.
+ * @default '200px'
+ */
+ minWidth?: string
+ /**
+ * Whether to show the code markup below.
+ * @default true
+ */
+ showMarkup?: boolean
+}
+
+const {
+ code,
+ class: classFromClass,
+ className,
+ initialWidth = '100%',
+ minWidth = '200px',
+ showMarkup = true
+} = Astro.props
+
+// Support both class and className props
+const containerClass = className || classFromClass
+
+let markup = Array.isArray(code) ? code.join('\n') : code
+markup = replacePlaceholdersInHtml(markup)
+
+const simplifiedMarkup = markup
+ .replace(
+ /<svg.*class="bd-placeholder-img(?:-lg)?(?: *?bd-placeholder-img-lg)? ?(.*?)".*?<\/svg>/g,
+ (match, classes) => `<img src="..."${classes ? ` class="${classes}"` : ''} alt="...">`
+ )
+---
+
+<div class="bd-example-snippet bd-code-snippet">
+ <div class="bd-example bd-example-resizable p-2">
+ <div
+ class:list={['bd-resizable-container', containerClass]}
+ style={`width: ${initialWidth}; min-width: ${minWidth};`}
+ >
+ <Fragment set:html={markup} />
+ </div>
+ </div>
+ {showMarkup && (
+ <Code code={simplifiedMarkup} lang="html" nestedInExample={true} />
+ )}
+</div>
<div class="container-fluid">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavDarkDropdown" aria-controls="navbarNavDarkDropdown" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
<div class="collapse navbar-collapse" id="navbarNavDarkDropdown">
<ul class="navbar-nav">
| `floatingConfig` | null, object, function | `null` | To change Bootstrap's default Floating UI config, see [Floating UI's configuration](https://floating-ui.com/docs/computePosition). When a function is used to create the Floating UI configuration, it's called with an object that contains the Bootstrap's default Floating UI configuration. It helps you use and merge the default with your own configuration. The function must return a configuration object for Floating UI. |
| `placement` | string | `'bottom-start'` | Placement of the dropdown menu. Physical placements: `'top'`, `'bottom'`, `'left'`, `'right'`. Logical placements (RTL-aware): `'start'`, `'end'`. All support alignment modifiers: `-start`, `-end`. Supports responsive prefixes like `'bottom-start md:end'`. |
| `reference` | string, element, object | `'toggle'` | Reference element of the dropdown menu. Accepts the values of `'toggle'`, `'parent'`, an HTMLElement reference or an object providing `getBoundingClientRect`. For more information refer to Floating UI's [virtual elements docs](https://floating-ui.com/docs/virtual-elements). |
+| `strategy` | string | `'absolute'` | Positioning strategy for the dropdown. Use `'absolute'` for default positioning, or `'fixed'` to escape containers with `overflow: hidden`. For more information refer to Floating UI's [strategy docs](https://floating-ui.com/docs/computePosition#strategy). |
| `submenuTrigger` | string | `'both'` | How submenus are triggered. Use `'click'` for click only, `'hover'` for hover only, or `'both'` for both click and hover activation. |
| `submenuDelay` | number | `100` | Delay in milliseconds before closing a submenu when the mouse leaves. Provides a grace period for diagonal mouse movement toward the submenu. |
</BsTable>
--- /dev/null
+---
+title: Nav overflow
+description: Automatically collapse navigation items into a "More" dropdown when space is limited using the Priority+ pattern.
+toc: true
+---
+
+## How it works
+
+The nav overflow component (also known as the "Priority+" pattern) automatically detects when navigation items don't fit within their container and moves them into a dropdown menu. This provides a responsive navigation experience without requiring different markup for different screen sizes.
+
+Here's what you need to know before getting started:
+
+- Add `data-bs-toggle="nav-overflow"` to any `.nav` element to enable automatic overflow detection.
+- **Responds to container size**, not viewport size. The component uses a ResizeObserver to monitor its own width, so it works perfectly in embedded contexts, documentation examples, and responsive containers.
+- Overflow items are cloned into a "More" dropdown menu while the originals are hidden.
+- Works with all nav styles: default, pills, tabs, and underline.
+- Active and disabled states are preserved in the overflow menu.
+
+<Callout name="info-prefersreducedmotion" />
+
+## Examples
+
+Add `data-bs-toggle="nav-overflow"` to your nav element. When items don't fit, they'll automatically move to a "More" dropdown. Drag the right edge of the container below to see how nav items automatically move to the "More" dropdown as space becomes limited.
+
+<ResizableExample code={`<ul class="nav nav-pills" data-bs-toggle="nav-overflow">
+ <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="#">Dashboard</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Products</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Services</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Analytics</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Reports</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Settings</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Help</a>
+ </li>
+ </ul>`} />
+
+### With tabs
+
+The overflow pattern works seamlessly with tabbed navigation:
+
+<ResizableExample code={`<ul class="nav nav-tabs" data-bs-toggle="nav-overflow">
+ <li class="nav-item">
+ <a class="nav-link active" aria-current="page" href="#">Overview</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Details</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">History</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Activity</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Comments</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Attachments</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Related</a>
+ </li>
+ </ul>`} />
+
+### With underline
+
+<ResizableExample code={`<ul class="nav nav-underline" data-bs-toggle="nav-overflow">
+ <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="#">Features</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Pricing</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">FAQs</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">About</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Contact</a>
+ </li>
+ </ul>`} />
+
+### Keep items visible
+
+Use the `.nav-overflow-keep` class on items that should never be moved to the overflow menu. These items will remain visible regardless of available space—useful for high-priority items like "Home" or action buttons.
+
+<ResizableExample code={`<ul class="nav nav-pills" data-bs-toggle="nav-overflow">
+ <li class="nav-item nav-overflow-keep">
+ <a class="nav-link active" aria-current="page" href="#">Home</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Products</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Services</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">About</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Blog</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Careers</a>
+ </li>
+ <li class="nav-item nav-overflow-keep">
+ <a class="nav-link" href="#">Contact</a>
+ </li>
+ </ul>`} />
+
+### With disabled items
+
+Disabled states are preserved when items move to the overflow menu:
+
+<ResizableExample code={`<ul class="nav nav-pills" data-bs-toggle="nav-overflow">
+ <li class="nav-item">
+ <a class="nav-link active" aria-current="page" href="#">Active</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Link</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Another link</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link disabled" aria-disabled="true">Disabled</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">More content</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Even more</a>
+ </li>
+ </ul>`} />
+
+### In a navbar
+
+The nav overflow pattern can also be used within a [navbar]([[docsref:/components/navbar]]) for horizontal navigation that adapts to available space:
+
+<ResizableExample code={`<nav class="navbar navbar-expand bg-body-tertiary">
+ <div class="container-fluid">
+ <a class="navbar-brand" href="#">Brand</a>
+ <ul class="navbar-nav" data-bs-toggle="nav-overflow">
+ <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="#">Features</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Pricing</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">About</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Contact</a>
+ </li>
+ </ul>
+ </div>
+ </nav>`} />
+
+## Customizing the toggle
+
+### Custom text
+
+Use the `moreText` option to customize the text shown in the overflow toggle button:
+
+```js
+const nav = document.querySelector('.nav')
+new bootstrap.NavOverflow(nav, {
+ moreText: 'See all'
+})
+```
+
+### Custom icon
+
+Provide a custom icon via the `moreIcon` option:
+
+```js
+const nav = document.querySelector('.nav')
+new bootstrap.NavOverflow(nav, {
+ moreIcon: '<i class="bi bi-three-dots"></i>',
+ moreText: '' // Hide text, show only icon
+})
+```
+
+### Minimum visible items
+
+Use the `threshold` option to ensure a minimum number of items remain visible before the overflow kicks in:
+
+```js
+const nav = document.querySelector('.nav')
+new bootstrap.NavOverflow(nav, {
+ threshold: 3 // Always keep at least 3 items visible
+})
+```
+
+## Usage
+
+### Via data attributes
+
+Add `data-bs-toggle="nav-overflow"` to any `.nav` element to automatically enable the overflow behavior.
+
+```html
+<ul class="nav nav-pills" data-bs-toggle="nav-overflow">
+ <li class="nav-item"><a class="nav-link" href="#">Link 1</a></li>
+ <li class="nav-item"><a class="nav-link" href="#">Link 2</a></li>
+ <li class="nav-item"><a class="nav-link" href="#">Link 3</a></li>
+ <!-- More items... -->
+</ul>
+```
+
+### Via JavaScript
+
+Initialize the nav overflow component manually:
+
+```js
+const navElement = document.querySelector('.nav')
+const navOverflow = new bootstrap.NavOverflow(navElement, {
+ moreText: 'More',
+ threshold: 2
+})
+```
+
+### Options
+
+<JsDataAttributes />
+
+<BsTable>
+| Name | Type | Default | Description |
+| --- | --- | --- | --- |
+| `moreText` | string | `'More'` | Text label for the overflow toggle button. |
+| `moreIcon` | string | `'<svg>...</svg>'` | SVG or HTML icon for the overflow toggle button. |
+| `threshold` | number | `0` | Minimum number of items to keep visible before showing overflow. |
+</BsTable>
+
+### Methods
+
+<Callout name="danger-async-methods" type="danger" />
+
+You can create a nav overflow instance with the constructor:
+
+```js
+const navOverflow = new bootstrap.NavOverflow('#myNav', {
+ threshold: 2
+})
+```
+
+<BsTable>
+| Method | Description |
+| --- | --- |
+| `dispose` | Destroys the nav overflow instance and restores items to their original positions. |
+| `getInstance` | *Static* method to get the nav overflow instance associated with a DOM element. |
+| `getOrCreateInstance` | *Static* method to get the nav overflow instance or create a new one if not initialized. |
+| `update` | Manually recalculates which items should overflow. Called automatically on resize. |
+</BsTable>
+
+### Events
+
+Bootstrap's nav overflow component exposes events for hooking into overflow functionality.
+
+<BsTable>
+| Event type | Description |
+| --- | --- |
+| `update.bs.navoverflow` | Fired when the overflow calculation is updated (on resize or manual update). |
+| `overflow.bs.navoverflow` | Fired when items are moved to the overflow menu. Event includes `overflowCount` and `visibleCount` properties. |
+</BsTable>
+
+```js
+const myNav = document.getElementById('myNav')
+
+myNav.addEventListener('overflow.bs.navoverflow', event => {
+ console.log(`${event.overflowCount} items moved to overflow`)
+ console.log(`${event.visibleCount} items still visible`)
+})
+```
---
title: Navbar
-description: Documentation and examples for Bootstrap’s powerful, responsive navigation header, the navbar. Includes support for branding, navigation, and more, including support for our collapse plugin.
+description: Documentation and examples for Bootstrap's powerful, responsive navigation header. The navbar includes support for branding, navigation, and more with built-in offcanvas for mobile.
toc: true
---
## How it works
-Here’s what you need to know before getting started with the navbar:
+Here's what you need to know before getting started with the navbar:
-- Navbars require a wrapping `.navbar` with `.navbar-expand{-sm|-md|-lg|-xl|-2xl}` for responsive collapsing and [color scheme](#color-schemes) classes.
+- Navbars require a wrapping `.navbar` with `.navbar-expand-lg{-sm|-md|-lg|-xl|-2xl}` for responsive collapsing and [color scheme](#color-schemes) classes.
- Navbars and their contents are fluid by default. Change the [container](#containers) to limit their horizontal width in different ways.
- Use our [margin]([[docsref:/utilities/margin]]), [padding]([[docsref:/utilities/padding]]), and [flex]([[docsref:/utilities/flex]]) utility classes for controlling spacing and alignment within navbars.
-- Navbars are responsive by default, but you can easily modify them to change that. Responsive behavior depends on our Collapse JavaScript plugin.
+- Navbars are responsive by default using our **offcanvas component**. On mobile, navigation links slide in from the side as a drawer.
- Ensure accessibility by using a `<nav>` element or, if using a more generic element such as a `<div>`, add a `role="navigation"` to every navbar to explicitly identify it as a landmark region for users of assistive technologies.
- Indicate the current item by using `aria-current="page"` for the current page or `aria-current="true"` for the current item in a set.
- `.navbar-brand` for your company, product, or project name.
- `.navbar-nav` for a full-height and lightweight navigation (including support for dropdowns).
-- `.navbar-toggler` for use with our collapse plugin and other [navigation toggling](#responsive-behaviors) behaviors.
+- `.navbar-toggler` for use with our offcanvas plugin and other [navigation toggling](#responsive-behaviors) behaviors.
- Flex and spacing utilities for any form controls and actions.
- `.navbar-text` for adding vertically centered strings of text.
-- `.collapse.navbar-collapse` for grouping and hiding navbar contents by a parent breakpoint.
-- Add an optional `.navbar-nav-scroll` to set a `max-height` and [scroll expanded navbar content](#scrolling).
-Here’s an example of all the sub-components included in a responsive light-themed navbar that automatically collapses at the `lg` (large) breakpoint.
+Here's an example of all the sub-components included in a responsive light-themed navbar that automatically shows an offcanvas drawer at the `lg` (large) breakpoint.
-<Example code={`<nav class="navbar navbar-expand-lg">
+<ResizableExample code={`<nav class="navbar navbar-expand-md bg-1">
<div class="container-fluid">
<a class="navbar-brand" href="#">Navbar</a>
- <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarOffcanvas" aria-controls="navbarOffcanvas" aria-expanded="false" aria-label="Toggle navigation">
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
- <div class="collapse navbar-collapse" id="navbarSupportedContent">
- <ul class="nav navbar-nav me-auto mb-2 mb-lg-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="#">Link</a>
- </li>
- <li class="nav-item dropdown">
- <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
- Dropdown
- </a>
- <ul class="dropdown-menu">
- <li><a class="dropdown-item" href="#">Action</a></li>
- <li><a class="dropdown-item" href="#">Another action</a></li>
- <li><hr class="dropdown-divider"></li>
- <li><a class="dropdown-item" href="#">Something else here</a></li>
- </ul>
- </li>
- <li class="nav-item">
- <a class="nav-link disabled" aria-disabled="true">Disabled</a>
- </li>
- </ul>
- <form class="d-flex" role="search">
- <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"/>
- <button class="btn btn-subtle theme-primary" type="submit">Search</button>
- </form>
+ <div class="offcanvas offcanvas-end" tabindex="-1" id="navbarOffcanvas" aria-labelledby="navbarOffcanvasLabel">
+ <div class="offcanvas-header">
+ <h5 class="offcanvas-title" id="navbarOffcanvasLabel">Menu</h5>
+ <CloseButton dismiss="offcanvas" />
+ </div>
+ <div class="offcanvas-body mb-2 mb-md-0">
+ <ul class="nav nav-pills me-auto">
+ <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="#">Link</a>
+ </li>
+ <li class="nav-item dropdown">
+ <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
+ Dropdown
+ </a>
+ <ul class="dropdown-menu">
+ <li><a class="dropdown-item" href="#">Action</a></li>
+ <li><a class="dropdown-item" href="#">Another action</a></li>
+ <li><hr class="dropdown-divider"></li>
+ <li><a class="dropdown-item" href="#">Something else here</a></li>
+ </ul>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link disabled" aria-disabled="true">Disabled</a>
+ </li>
+ </ul>
+ <form class="d-flex" role="search">
+ <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"/>
+ <button class="btn btn-icon btn-solid theme-secondary" type="submit">
+ <svg class="bi" width="16" height="16"><use href="#search" /></svg>
+ </button>
+ </form>
+ </div>
</div>
</div>
</nav>`} />
Add your text within an element with the `.navbar-brand` class.
<Example code={`<!-- As a link -->
- <nav class="navbar bg-body-tertiary">
+ <nav class="navbar bg-1 fg-2">
<div class="container-fluid">
<a class="navbar-brand" href="#">Navbar</a>
</div>
</nav>
<!-- As a heading -->
- <nav class="navbar bg-body-tertiary">
+ <nav class="navbar bg-1 fg-2">
<div class="container-fluid">
<span class="navbar-brand mb-0 h1">Navbar</span>
</div>
You can replace the text within the `.navbar-brand` with an `<img>`.
-<Example code={`<nav class="navbar bg-body-tertiary">
+<Example code={`<nav class="navbar bg-1 fg-2">
<div class="container">
<a class="navbar-brand" href="#">
<img src="/docs/${getConfig().docs_version}/assets/brand/bootstrap-logo.svg" alt="Bootstrap" width="30" height="24">
You can also make use of some additional utilities to add an image and text at the same time. Note the addition of `.d-inline-block` and `.align-text-top` on the `<img>`.
-<Example code={`<nav class="navbar bg-body-tertiary">
+<Example code={`<nav class="navbar bg-1 fg-2">
<div class="container-fluid">
<a class="navbar-brand" href="#">
<img src="/docs/${getConfig().docs_version}/assets/brand/bootstrap-logo.svg" alt="Logo" width="30" height="24" class="d-inline-block align-text-top">
Please note that you should also add the `aria-current` attribute on the active `.nav-link`.
-<Example code={`<nav class="navbar navbar-expand-lg bg-body-tertiary">
+<ResizableExample code={`<nav class="navbar navbar-expand-sm bg-1 fg-2">
<div class="container-fluid">
<a class="navbar-brand" href="#">Navbar</a>
- <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
- <div class="collapse navbar-collapse" id="navbarNav">
- <ul class="navbar-nav">
- <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="#">Features</a>
- </li>
- <li class="nav-item">
- <a class="nav-link" href="#">Pricing</a>
- </li>
- <li class="nav-item">
- <a class="nav-link disabled" aria-disabled="true">Disabled</a>
- </li>
- </ul>
+ <div class="offcanvas offcanvas-end" tabindex="-1" id="navbarNav" aria-labelledby="navbarNavLabel">
+ <div class="offcanvas-header">
+ <h5 class="offcanvas-title" id="navbarNavLabel">Menu</h5>
+ <CloseButton dismiss="offcanvas" />
+ </div>
+ <div class="offcanvas-body">
+ <ul class="navbar-nav">
+ <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="#">Features</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Pricing</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link disabled" aria-disabled="true">Disabled</a>
+ </li>
+ </ul>
+ </div>
</div>
</div>
</nav>`} />
And because we use classes for our navs, you can avoid the list-based approach entirely if you like.
-<Example code={`<nav class="navbar navbar-expand-lg bg-body-tertiary">
+<ResizableExample code={`<nav class="navbar navbar-expand-sm bg-1 fg-2">
<div class="container-fluid">
<a class="navbar-brand" href="#">Navbar</a>
- <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
- <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
- <div class="navbar-nav">
- <a class="nav-link active" aria-current="page" href="#">Home</a>
- <a class="nav-link" href="#">Features</a>
- <a class="nav-link" href="#">Pricing</a>
- <a class="nav-link disabled" aria-disabled="true">Disabled</a>
+ <div class="offcanvas offcanvas-end" tabindex="-1" id="navbarNavAltMarkup" aria-labelledby="navbarNavAltMarkupLabel">
+ <div class="offcanvas-header">
+ <h5 class="offcanvas-title" id="navbarNavAltMarkupLabel">Menu</h5>
+ <CloseButton dismiss="offcanvas" />
+ </div>
+ <div class="offcanvas-body">
+ <div class="nav nav-pills navbar-nav">
+ <a class="nav-link active" aria-current="page" href="#">Home</a>
+ <a class="nav-link" href="#">Features</a>
+ <a class="nav-link" href="#">Pricing</a>
+ <a class="nav-link disabled" aria-disabled="true">Disabled</a>
+ </div>
</div>
</div>
</div>
You can also use dropdowns in your navbar. Dropdown menus require a wrapping element for positioning, so be sure to use separate and nested elements for `.nav-item` and `.nav-link` as shown below.
-<Example code={`<nav class="navbar navbar-expand-lg bg-body-tertiary">
+<ResizableExample code={`<nav class="navbar navbar-expand-lg bg-1 fg-2">
<div class="container-fluid">
<a class="navbar-brand" href="#">Navbar</a>
- <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
- <div class="collapse navbar-collapse" id="navbarNavDropdown">
- <ul class="navbar-nav">
- <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="#">Features</a>
- </li>
- <li class="nav-item">
- <a class="nav-link" href="#">Pricing</a>
- </li>
- <li class="nav-item dropdown">
- <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
- Dropdown link
- </a>
- <ul class="dropdown-menu">
- <li><a class="dropdown-item" href="#">Action</a></li>
- <li><a class="dropdown-item" href="#">Another action</a></li>
- <li><a class="dropdown-item" href="#">Something else here</a></li>
- </ul>
- </li>
- </ul>
+ <div class="offcanvas offcanvas-end" tabindex="-1" id="navbarNavDropdown" aria-labelledby="navbarNavDropdownLabel">
+ <div class="offcanvas-header">
+ <h5 class="offcanvas-title" id="navbarNavDropdownLabel">Menu</h5>
+ <CloseButton dismiss="offcanvas" />
+ </div>
+ <div class="offcanvas-body">
+ <ul class="navbar-nav">
+ <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="#">Features</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Pricing</a>
+ </li>
+ <li class="nav-item dropdown">
+ <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
+ Dropdown link
+ </a>
+ <ul class="dropdown-menu">
+ <li><a class="dropdown-item" href="#">Action</a></li>
+ <li><a class="dropdown-item" href="#">Another action</a></li>
+ <li><a class="dropdown-item" href="#">Something else here</a></li>
+ </ul>
+ </li>
+ </ul>
+ </div>
</div>
</div>
</nav>`} />
Place various form controls and components within a navbar:
-<Example code={`<nav class="navbar bg-body-tertiary">
+<Example code={`<nav class="navbar bg-1 fg-2">
<div class="container-fluid">
<form class="d-flex" role="search">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"/>
Immediate child elements of `.navbar` use flex layout and will default to `justify-content: space-between`. Use additional [flex utilities]([[docsref:/utilities/flex]]) as needed to adjust this behavior.
-<Example code={`<nav class="navbar bg-body-tertiary">
+<Example code={`<nav class="navbar bg-1 fg-2">
<div class="container-fluid">
<a class="navbar-brand">Navbar</a>
<form class="d-flex" role="search">
Input groups work, too. If your navbar is an entire form, or mostly a form, you can use the `<form>` element as the container and save some HTML.
-<Example code={`<nav class="navbar bg-body-tertiary">
+<Example code={`<nav class="navbar bg-1 fg-2">
<form class="container-fluid">
<div class="input-group">
<span class="input-group-text" id="basic-addon1">@</span>
Various buttons are supported as part of these navbar forms, too. This is also a great reminder that vertical alignment utilities can be used to align different sized elements.
-<Example code={`<nav class="navbar bg-body-tertiary">
+<Example code={`<nav class="navbar bg-1 fg-2">
<form class="container-fluid justify-content-start">
<button class="btn btn-outline-success me-2" type="button">Main button</button>
<button class="btn btn-sm btn-outline-secondary" type="button">Smaller button</button>
Navbars may contain bits of text with the help of `.navbar-text`. This class adjusts vertical alignment and horizontal spacing for strings of text.
-<Example code={`<nav class="navbar bg-body-tertiary">
+<Example code={`<nav class="navbar bg-1 fg-2">
<div class="container-fluid">
<span class="navbar-text">
Navbar text with an inline element
Mix and match with other components and utilities as needed.
-<Example code={`<nav class="navbar navbar-expand-lg bg-body-tertiary">
+<ResizableExample code={`<nav class="navbar navbar-expand-md bg-1 fg-2">
<div class="container-fluid">
<a class="navbar-brand" href="#">Navbar w/ text</a>
- <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
- <div class="collapse navbar-collapse" id="navbarText">
- <ul class="navbar-nav me-auto mb-2 mb-lg-0">
+ <div class="offcanvas offcanvas-end" tabindex="-1" id="navbarText" aria-labelledby="navbarTextLabel">
+ <div class="offcanvas-header">
+ <h5 class="offcanvas-title" id="navbarTextLabel">Menu</h5>
+ <CloseButton dismiss="offcanvas" />
+ </div>
+ <div class="offcanvas-body">
+ <ul class="navbar-nav me-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="#">Features</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Pricing</a>
+ </li>
+ </ul>
+ <span class="navbar-text">
+ Navbar text with an inline element
+ </span>
+ </div>
+ </div>
+ </div>
+ </nav>`} />
+
+## Color schemes
+
+Navbar themes are easier than ever thanks to Bootstrap's combination of Sass and CSS variables. The default is our "light navbar" for use with light background colors, but you can also apply `data-bs-theme="dark"` to the `.navbar` parent for dark background colors. Then, customize with `.bg-*` and additional utilities.
+
+<ResizableExample className="d-flex flex-column gap-2" showMarkup={false} code={`
+<nav class="navbar navbar-expand-md bg-body border-bottom border-body" data-bs-theme="dark">
+ <div class="container-fluid">
+ <a class="navbar-brand" href="#">Navbar</a>
+ <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarColor01" aria-controls="navbarColor01" aria-expanded="false" aria-label="Toggle navigation">
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
+ </button>
+ <div class="offcanvas offcanvas-end" tabindex="-1" id="navbarColor01" aria-labelledby="navbarColor01Label">
+ <div class="offcanvas-header">
+ <h5 class="offcanvas-title" id="navbarColor01Label">Menu</h5>
+ <CloseButton dismiss="offcanvas" />
+ </div>
+ <div class="offcanvas-body">
+ <ul class="navbar-nav me-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="#">Pricing</a>
</li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">About</a>
+ </li>
</ul>
- <span class="navbar-text">
- Navbar text with an inline element
- </span>
+ <form class="d-flex" role="search">
+ <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"/>
+ <button class="btn btn-outline theme-secondary" type="submit">Search</button>
+ </form>
</div>
</div>
- </nav>`} />
-
-## Color schemes
-
-Navbar themes are easier than ever thanks to Bootstrap’s combination of Sass and CSS variables. The default is our “light navbar” for use with light background colors, but you can also apply `data-bs-theme="dark"` to the `.navbar` parent for dark background colors. Then, customize with `.bg-*` and additional utilities.
-
-<Example showMarkup={false} code={`
-<nav class="navbar navbar-expand-lg bg-dark border-bottom border-body" data-bs-theme="dark">
- <div class="container-fluid">
- <a class="navbar-brand" href="#">Navbar</a>
- <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarColor01" aria-controls="navbarColor01" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
- </button>
- <div class="collapse navbar-collapse" id="navbarColor01">
- <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</a>
- </li>
- <li class="nav-item">
- <a class="nav-link" href="#">Features</a>
- </li>
- <li class="nav-item">
- <a class="nav-link" href="#">Pricing</a>
- </li>
- <li class="nav-item">
- <a class="nav-link" href="#">About</a>
- </li>
- </ul>
- <form class="d-flex" role="search">
- <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>
-<nav class="navbar navbar-expand-lg bg-primary" data-bs-theme="dark">
+<nav class="navbar navbar-expand-md bg-primary" data-bs-theme="dark">
<div class="container-fluid">
<a class="navbar-brand" href="#">Navbar</a>
- <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarColor02" aria-controls="navbarColor02" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarColor02" aria-controls="navbarColor02" aria-expanded="false" aria-label="Toggle navigation">
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
- <div class="collapse navbar-collapse" id="navbarColor02">
- <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</a>
- </li>
- <li class="nav-item">
- <a class="nav-link" href="#">Features</a>
- </li>
- <li class="nav-item">
- <a class="nav-link" href="#">Pricing</a>
- </li>
- <li class="nav-item">
- <a class="nav-link" href="#">About</a>
- </li>
- </ul>
- <form class="d-flex" role="search">
- <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 class="offcanvas offcanvas-end" tabindex="-1" id="navbarColor02" aria-labelledby="navbarColor02Label">
+ <div class="offcanvas-header">
+ <h5 class="offcanvas-title" id="navbarColor02Label">Menu</h5>
+ <CloseButton dismiss="offcanvas" />
+ </div>
+ <div class="offcanvas-body">
+ <ul class="navbar-nav me-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="#">Features</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Pricing</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">About</a>
+ </li>
+ </ul>
+ <form class="d-flex" role="search">
+ <input class="form-control me-2" data-bs-theme="light" type="search" placeholder="Search" aria-label="Search"/>
+ <button class="btn btn-solid theme-inverse" type="submit">Search</button>
+ </form>
+ </div>
</div>
</div>
</nav>
-<nav class="navbar navbar-expand-lg" style="background-color: #e3f2fd;" data-bs-theme="light">
+<nav class="navbar navbar-expand-md bg-1" data-bs-theme="light">
<div class="container-fluid">
<a class="navbar-brand" href="#">Navbar</a>
- <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarColor03" aria-controls="navbarColor03" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarColor03" aria-controls="navbarColor03" aria-expanded="false" aria-label="Toggle navigation">
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
- <div class="collapse navbar-collapse" id="navbarColor03">
- <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</a>
- </li>
- <li class="nav-item">
- <a class="nav-link" href="#">Features</a>
- </li>
- <li class="nav-item">
- <a class="nav-link" href="#">Pricing</a>
- </li>
- <li class="nav-item">
- <a class="nav-link" href="#">About</a>
- </li>
- </ul>
- <form class="d-flex" role="search">
- <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"/>
- <button class="btn btn-outline-primary" type="submit">Search</button>
- </form>
+ <div class="offcanvas offcanvas-end" tabindex="-1" id="navbarColor03" aria-labelledby="navbarColor03Label">
+ <div class="offcanvas-header">
+ <h5 class="offcanvas-title" id="navbarColor03Label">Menu</h5>
+ <CloseButton dismiss="offcanvas" />
+ </div>
+ <div class="offcanvas-body">
+ <ul class="navbar-nav me-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="#">Features</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">Pricing</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="#">About</a>
+ </li>
+ </ul>
+ <form class="d-flex" role="search">
+ <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"/>
+ <button class="btn btn-outline-primary" type="submit">Search</button>
+ </form>
+ </div>
</div>
</div>
</nav>
`} />
```html
-<nav class="navbar bg-dark border-bottom border-body" data-bs-theme="dark">
+<nav class="navbar bg-body border-bottom border-body" data-bs-theme="dark">
<!-- Navbar content -->
</nav>
## Containers
-Although it’s not required, you can wrap a navbar in a `.container` to center it on a page–though note that an inner container is still required. Or you can add a container inside the `.navbar` to only center the contents of a [fixed or static top navbar](#placement).
+Although it's not required, you can wrap a navbar in a `.container` to center it on a page–though note that an inner container is still required. Or you can add a container inside the `.navbar` to only center the contents of a [fixed or static top navbar](#placement).
<Example code={`<div class="container">
- <nav class="navbar navbar-expand-lg bg-body-tertiary">
+ <nav class="navbar navbar-expand-lg bg-1 fg-2">
<div class="container-fluid">
<a class="navbar-brand" href="#">Navbar</a>
</div>
Use any of the responsive containers to change how wide the content in your navbar is presented.
-<Example code={`<nav class="navbar navbar-expand-lg bg-body-tertiary">
+<Example code={`<nav class="navbar navbar-expand-lg bg-1 fg-2">
<div class="container-md">
<a class="navbar-brand" href="#">Navbar</a>
</div>
Use our [position utilities]([[docsref:/utilities/position]]) to place navbars in non-static positions. Choose from fixed to the top, fixed to the bottom, stickied to the top (scrolls with the page until it reaches the top, then stays there), or stickied to the bottom (scrolls with the page until it reaches the bottom, then stays there).
-Fixed navbars use `position: fixed`, meaning they’re pulled from the normal flow of the DOM and may require custom CSS (e.g., `padding-top` on the `<body>`) to prevent overlap with other elements.
-
-<Example code={`<nav class="navbar bg-body-tertiary">
- <div class="container-fluid">
- <a class="navbar-brand" href="#">Default</a>
- </div>
- </nav>`} />
+Fixed navbars use `position: fixed`, meaning they're pulled from the normal flow of the DOM and may require custom CSS (e.g., `padding-top` on the `<body>`) to prevent overlap with other elements.
-<Example code={`<nav class="navbar fixed-top bg-body-tertiary">
- <div class="container-fluid">
- <a class="navbar-brand" href="#">Fixed top</a>
- </div>
- </nav>`} />
-
-<Example code={`<nav class="navbar fixed-bottom bg-body-tertiary">
- <div class="container-fluid">
- <a class="navbar-brand" href="#">Fixed bottom</a>
- </div>
- </nav>`} />
-
-<Example code={`<nav class="navbar sticky-top bg-body-tertiary">
- <div class="container-fluid">
- <a class="navbar-brand" href="#">Sticky top</a>
- </div>
- </nav>`} />
+<NavbarPlacementPlayground />
-<Example code={`<nav class="navbar sticky-bottom bg-body-tertiary">
- <div class="container-fluid">
- <a class="navbar-brand" href="#">Sticky bottom</a>
- </div>
- </nav>`} />
+## Responsive behaviors
-## Scrolling
+Navbars can use `.navbar-toggler`, and `.navbar-expand-lg{-sm|-md|-lg|-xl|-2xl}` classes to determine when their content appears in an offcanvas drawer or inline. In combination with other utilities, you can easily choose when to show or hide particular elements.
-Add `.navbar-nav-scroll` to a `.navbar-nav` (or other navbar sub-component) to enable vertical scrolling within the toggleable contents of a collapsed navbar. By default, scrolling kicks in at `75vh` (or 75% of the viewport height), but you can override that with the local CSS custom property `--bs-navbar-height` or custom styles. At larger viewports when the navbar is expanded, content will appear as it does in a default navbar.
+For navbars that never collapse, add the `.navbar-expand-lg` class on the navbar. For navbars that always show the offcanvas drawer, don't add any `.navbar-expand-lg` class.
-Please note that this behavior comes with a potential drawback of `overflow`—when setting `overflow-y: auto` (required to scroll the content here), `overflow-x` is the equivalent of `auto`, which will crop some horizontal content.
+### Offcanvas drawer
-Here’s an example navbar using `.navbar-nav-scroll` with `style="--bs-scroll-height: 100px;"`, with some extra margin utilities for optimum spacing.
+By default, navbars use the [offcanvas component]([[docsref:/components/offcanvas]]) for their responsive behavior. This provides a modern drawer-style menu that slides in from any side of the screen.
-<Example code={`<nav class="navbar navbar-expand-lg bg-body-tertiary">
- <div class="container-fluid">
- <a class="navbar-brand" href="#">Navbar scroll</a>
- <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarScroll" aria-controls="navbarScroll" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
- </button>
- <div class="collapse navbar-collapse" id="navbarScroll">
- <ul class="navbar-nav me-auto my-2 my-lg-0 navbar-nav-scroll" style="--bs-scroll-height: 100px;">
- <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="#">Link</a>
- </li>
- <li class="nav-item dropdown">
- <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
- Link
- </a>
- <ul class="dropdown-menu">
- <li><a class="dropdown-item" href="#">Action</a></li>
- <li><a class="dropdown-item" href="#">Another action</a></li>
- <li><hr class="dropdown-divider"></li>
- <li><a class="dropdown-item" href="#">Something else here</a></li>
- </ul>
- </li>
- <li class="nav-item">
- <a class="nav-link disabled" aria-disabled="true">Link</a>
- </li>
- </ul>
- <form class="d-flex" role="search">
- <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"/>
- <button class="btn btn-outline-success" type="submit">Search</button>
- </form>
- </div>
- </div>
- </nav>`} />
+#### Drawer placement
-## Responsive behaviors
+You can customize which side the drawer appears from using offcanvas placement classes:
-Navbars can use `.navbar-toggler`, `.navbar-collapse`, and `.navbar-expand{-sm|-md|-lg|-xl|-2xl}` classes to determine when their content collapses behind a button. In combination with other utilities, you can easily choose when to show or hide particular elements.
+- `.offcanvas-start` - slides in from the left (or right in RTL)
+- `.offcanvas-end` - slides in from the right (or left in RTL)
+- `.offcanvas-top` - slides in from the top
+- `.offcanvas-bottom` - slides in from the bottom
-For navbars that never collapse, add the `.navbar-expand` class on the navbar. For navbars that always collapse, don’t add any `.navbar-expand` class.
+These examples omit the `.navbar-expand-lg-*` class to always show the drawer behavior. Click the toggler to see the drawer slide in from different directions.
-### Toggler
-
-Navbar togglers are left-aligned by default, but should they follow a sibling element like a `.navbar-brand`, they’ll automatically be aligned to the far right. Reversing your markup will reverse the placement of the toggler. Below are examples of different toggle styles.
-
-With no `.navbar-brand` shown at the smallest breakpoint:
-
-<Example code={`<nav class="navbar navbar-expand-lg bg-body-tertiary">
+<ResizableExample code={`<nav class="navbar navbar-expand-md bg-1 fg-2">
<div class="container-fluid">
- <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarTogglerDemo01" aria-controls="navbarTogglerDemo01" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <a class="navbar-brand" href="#">Left Drawer</a>
+ <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarLeftDrawer" aria-controls="navbarLeftDrawer" aria-expanded="false" aria-label="Toggle navigation">
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
- <div class="collapse navbar-collapse" id="navbarTogglerDemo01">
- <a class="navbar-brand" href="#">Hidden brand</a>
- <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</a>
- </li>
- <li class="nav-item">
- <a class="nav-link" href="#">Link</a>
- </li>
- <li class="nav-item">
- <a class="nav-link disabled" aria-disabled="true">Disabled</a>
- </li>
- </ul>
- <form class="d-flex" role="search">
- <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"/>
- <button class="btn btn-outline-success" type="submit">Search</button>
- </form>
+ <div class="offcanvas offcanvas-start" tabindex="-1" id="navbarLeftDrawer" aria-labelledby="navbarLeftDrawerLabel">
+ <div class="offcanvas-header">
+ <h5 class="offcanvas-title" id="navbarLeftDrawerLabel">Menu</h5>
+ <CloseButton dismiss="offcanvas" />
+ </div>
+ <div class="offcanvas-body">
+ <ul class="navbar-nav me-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="#">Link</a></li>
+ <li class="nav-item"><a class="nav-link disabled" aria-disabled="true">Disabled</a></li>
+ </ul>
+ </div>
</div>
</div>
</nav>`} />
-With a brand name shown on the left and toggler on the right:
-
-<Example code={`<nav class="navbar navbar-expand-lg bg-body-tertiary">
+<ResizableExample code={`<nav class="navbar navbar-expand-md bg-1 fg-2">
<div class="container-fluid">
- <a class="navbar-brand" href="#">Navbar</a>
- <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarTogglerDemo02" aria-controls="navbarTogglerDemo02" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <a class="navbar-brand" href="#">Top Drawer</a>
+ <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarTopDrawer" aria-controls="navbarTopDrawer" aria-expanded="false" aria-label="Toggle navigation">
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
- <div class="collapse navbar-collapse" id="navbarTogglerDemo02">
- <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</a>
- </li>
- <li class="nav-item">
- <a class="nav-link" href="#">Link</a>
- </li>
- <li class="nav-item">
- <a class="nav-link disabled" aria-disabled="true">Disabled</a>
- </li>
- </ul>
- <form class="d-flex" role="search">
- <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"/>
- <button class="btn btn-outline-success" type="submit">Search</button>
- </form>
+ <div class="offcanvas offcanvas-top" tabindex="-1" id="navbarTopDrawer" aria-labelledby="navbarTopDrawerLabel">
+ <div class="offcanvas-header">
+ <h5 class="offcanvas-title" id="navbarTopDrawerLabel">Menu</h5>
+ <CloseButton dismiss="offcanvas" />
+ </div>
+ <div class="offcanvas-body">
+ <ul class="navbar-nav me-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="#">Link</a></li>
+ <li class="nav-item"><a class="nav-link disabled" aria-disabled="true">Disabled</a></li>
+ </ul>
+ </div>
</div>
</div>
</nav>`} />
-With a toggler on the left and brand name on the right:
+### Toggler
-<Example code={`<nav class="navbar navbar-expand-lg bg-body-tertiary">
- <div class="container-fluid">
- <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarTogglerDemo03" aria-controls="navbarTogglerDemo03" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
- </button>
- <a class="navbar-brand" href="#">Navbar</a>
- <div class="collapse navbar-collapse" id="navbarTogglerDemo03">
- <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</a>
- </li>
- <li class="nav-item">
- <a class="nav-link" href="#">Link</a>
- </li>
- <li class="nav-item">
- <a class="nav-link disabled" aria-disabled="true">Disabled</a>
- </li>
- </ul>
- <form class="d-flex" role="search">
- <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"/>
- <button class="btn btn-outline-success" type="submit">Search</button>
- </form>
- </div>
- </div>
- </nav>`} />
+Navbar togglers are left-aligned by default, but should they follow a sibling element like a `.navbar-brand`, they'll automatically be aligned to the far right. Reversing your markup will reverse the placement of the toggler.
-### External content
+These examples omit the `.navbar-expand-lg-*` class to always show the collapsed state with the toggler visible. Click the toggler to open the offcanvas drawer.
-Sometimes you want to use the collapse plugin to trigger a container element for content that structurally sits outside of the `.navbar` . Because our plugin works on the `id` and `data-bs-target` matching, that’s easily done!
+With no `.navbar-brand` shown (hidden inside the drawer):
-<Example code={`<div class="collapse" id="navbarToggleExternalContent" data-bs-theme="dark">
- <div class="bg-dark p-4">
- <h5 class="text-body-emphasis h4">Collapsed content</h5>
- <span class="text-body-secondary">Toggleable via the navbar brand.</span>
- </div>
- </div>
- <nav class="navbar navbar-dark bg-dark">
+<ResizableExample code={`<nav class="navbar navbar-expand-md bg-1 fg-2">
<div class="container-fluid">
- <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarToggleExternalContent" aria-controls="navbarToggleExternalContent" aria-expanded="false" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarTogglerDemo01" aria-controls="navbarTogglerDemo01" aria-expanded="false" aria-label="Toggle navigation">
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
+ <div class="offcanvas offcanvas-end" tabindex="-1" id="navbarTogglerDemo01" aria-labelledby="navbarTogglerDemo01Label">
+ <div class="offcanvas-header">
+ <h5 class="offcanvas-title" id="navbarTogglerDemo01Label">Hidden brand</h5>
+ <CloseButton dismiss="offcanvas" />
+ </div>
+ <div class="offcanvas-body">
+ <a class="navbar-brand" href="#">Hidden brand</a>
+ <ul class="navbar-nav me-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="#">Link</a></li>
+ <li class="nav-item"><a class="nav-link disabled" aria-disabled="true">Disabled</a></li>
+ </ul>
+ <form class="d-flex" role="search">
+ <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"/>
+ <button class="btn btn-outline-success" type="submit">Search</button>
+ </form>
+ </div>
+ </div>
</div>
</nav>`} />
-When you do this, we recommend including additional JavaScript to move the focus programmatically to the container when it is opened. Otherwise, keyboard users and users of assistive technologies will likely have a hard time finding the newly revealed content - particularly if the container that was opened comes *before* the toggler in the document’s structure. We also recommend making sure that the toggler has the `aria-controls` attribute, pointing to the `id` of the content container. In theory, this allows assistive technology users to jump directly from the toggler to the container it controls–but support for this is currently quite patchy.
-
-### Offcanvas
-
-Transform your expanding and collapsing navbar into an offcanvas drawer with the [offcanvas component]([[docsref:/components/offcanvas]]). We extend both the offcanvas default styles and use our `.navbar-expand-*` classes to create a dynamic and flexible navigation sidebar.
-
-In the example below, to create an offcanvas navbar that is always collapsed across all breakpoints, omit the `.navbar-expand-*` class entirely.
+With a brand name shown on the left and toggler on the right:
-<Example code={`<nav class="navbar bg-body-tertiary fixed-top">
+<ResizableExample code={`<nav class="navbar bg-1 fg-2">
<div class="container-fluid">
- <a class="navbar-brand" href="#">Offcanvas navbar</a>
- <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasNavbar" aria-controls="offcanvasNavbar" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <a class="navbar-brand" href="#">Navbar</a>
+ <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarTogglerDemo02" aria-controls="navbarTogglerDemo02" aria-expanded="false" aria-label="Toggle navigation">
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
- <div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasNavbar" aria-labelledby="offcanvasNavbarLabel">
+ <div class="offcanvas offcanvas-end" tabindex="-1" id="navbarTogglerDemo02" aria-labelledby="navbarTogglerDemo02Label">
<div class="offcanvas-header">
- <h5 class="offcanvas-title" id="offcanvasNavbarLabel">Offcanvas</h5>
+ <h5 class="offcanvas-title" id="navbarTogglerDemo02Label">Menu</h5>
<CloseButton dismiss="offcanvas" />
</div>
<div class="offcanvas-body">
- <ul class="navbar-nav justify-content-end flex-grow-1 pe-3">
- <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="#">Link</a>
- </li>
- <li class="nav-item dropdown">
- <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
- Dropdown
- </a>
- <ul class="dropdown-menu">
- <li><a class="dropdown-item" href="#">Action</a></li>
- <li><a class="dropdown-item" href="#">Another action</a></li>
- <li>
- <hr class="dropdown-divider">
- </li>
- <li><a class="dropdown-item" href="#">Something else here</a></li>
- </ul>
- </li>
+ <ul class="navbar-nav me-auto mb-2">
+ <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="#">Link</a></li>
+ <li class="nav-item"><a class="nav-link disabled" aria-disabled="true">Disabled</a></li>
</ul>
- <form class="d-flex mt-3" role="search">
+ <form class="d-flex" role="search">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"/>
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</div>
</nav>`} />
-To create an offcanvas navbar that expands into a normal navbar at a specific breakpoint like `lg`, use `.navbar-expand-lg`.
-
-```html
-<nav class="navbar navbar-expand-lg bg-body-tertiary fixed-top">
- <a class="navbar-brand" href="#">Offcanvas navbar</a>
- <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarOffcanvasLg" aria-controls="navbarOffcanvasLg" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
- </button>
- <div class="offcanvas offcanvas-end" tabindex="-1" id="navbarOffcanvasLg" aria-labelledby="navbarOffcanvasLgLabel">
- ...
- </div>
-</nav>
-```
-
-When using offcanvas in a dark navbar, be aware that you may need to have a dark background on the offcanvas content to avoid the text becoming illegible. In the example below, we add `.navbar-dark` and `.bg-dark` to the `.navbar`, `.text-bg-dark` to the `.offcanvas`, `.dropdown-menu-dark` to `.dropdown-menu`, and `.btn-close-white` to `.btn-close` for proper styling with a dark offcanvas.
+With a toggler on the left and brand name on the right:
-<Example code={`<nav class="navbar navbar-dark bg-dark fixed-top">
+<ResizableExample code={`<nav class="navbar bg-1 fg-2">
<div class="container-fluid">
- <a class="navbar-brand" href="#">Offcanvas dark navbar</a>
- <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasDarkNavbar" aria-controls="offcanvasDarkNavbar" aria-label="Toggle navigation">
- <span class="navbar-toggler-icon"></span>
+ <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarTogglerDemo03" aria-controls="navbarTogglerDemo03" aria-expanded="false" aria-label="Toggle navigation">
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
</button>
- <div class="offcanvas offcanvas-end text-bg-dark" tabindex="-1" id="offcanvasDarkNavbar" aria-labelledby="offcanvasDarkNavbarLabel">
+ <a class="navbar-brand" href="#">Navbar</a>
+ <div class="offcanvas offcanvas-end" tabindex="-1" id="navbarTogglerDemo03" aria-labelledby="navbarTogglerDemo03Label">
<div class="offcanvas-header">
- <h5 class="offcanvas-title" id="offcanvasDarkNavbarLabel">Dark offcanvas</h5>
+ <h5 class="offcanvas-title" id="navbarTogglerDemo03Label">Menu</h5>
<CloseButton dismiss="offcanvas" />
</div>
<div class="offcanvas-body">
- <ul class="navbar-nav justify-content-end flex-grow-1 pe-3">
- <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="#">Link</a>
- </li>
- <li class="nav-item dropdown">
- <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
- Dropdown
- </a>
- <ul class="dropdown-menu dropdown-menu-dark">
- <li><a class="dropdown-item" href="#">Action</a></li>
- <li><a class="dropdown-item" href="#">Another action</a></li>
- <li>
- <hr class="dropdown-divider">
- </li>
- <li><a class="dropdown-item" href="#">Something else here</a></li>
- </ul>
- </li>
+ <ul class="navbar-nav me-auto mb-2">
+ <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="#">Link</a></li>
+ <li class="nav-item"><a class="nav-link disabled" aria-disabled="true">Disabled</a></li>
</ul>
- <form class="d-flex mt-3" role="search">
+ <form class="d-flex" role="search">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"/>
- <button class="btn btn-success" type="submit">Search</button>
+ <button class="btn btn-outline-success" type="submit">Search</button>
</form>
</div>
</div>
</div>
</nav>`} />
+### External content
+
+Sometimes you want to use the offcanvas plugin to trigger a container element for content that structurally sits outside of the `.navbar`. Because our plugin works on the `id` and `data-bs-target` matching, that's easily done!
+
+<ResizableExample code={`<div class="offcanvas offcanvas-top" tabindex="-1" id="navbarToggleExternalContent" data-bs-theme="dark" aria-labelledby="navbarToggleExternalContentLabel">
+ <div class="offcanvas-header">
+ <h5 class="offcanvas-title" id="navbarToggleExternalContentLabel">Collapsed content</h5>
+ <CloseButton dismiss="offcanvas" />
+ </div>
+ <div class="offcanvas-body">
+ <span class="text-body-secondary">Toggleable via the navbar toggler.</span>
+ </div>
+ </div>
+ <nav class="navbar bg-body" data-bs-theme="dark">
+ <div class="container-fluid">
+ <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarToggleExternalContent" aria-controls="navbarToggleExternalContent" aria-expanded="false" aria-label="Toggle navigation">
+ <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
+ </button>
+ </div>
+ </nav>`} />
+
+When you do this, we recommend including additional JavaScript to move the focus programmatically to the container when it is opened. Otherwise, keyboard users and users of assistive technologies will likely have a hard time finding the newly revealed content - particularly if the container that was opened comes *before* the toggler in the document's structure. We also recommend making sure that the toggler has the `aria-controls` attribute, pointing to the `id` of the content container. In theory, this allows assistive technology users to jump directly from the toggler to the container it controls–but support for this is currently quite patchy.
+
## CSS
### Variables
<ScssDocs name="navbar-nav-css-vars" file="scss/_navbar.scss" />
-Customization through CSS variables can be seen on the `.navbar-dark` class where we override specific values without adding duplicate CSS selectors.
+Customization through CSS variables can be seen on navbars with `data-bs-theme="dark"` where we override specific values without adding duplicate CSS selectors.
<ScssDocs name="navbar-dark-css-vars" file="scss/_navbar.scss" />
## Placement
-There’s no default placement for offcanvas components, so you must add one of the modifier classes below.
+There's no default placement for offcanvas components, so you must add one of the modifier classes below.
- `.offcanvas-start` places offcanvas on the left of the viewport (shown above)
- `.offcanvas-end` places offcanvas on the right of the viewport
- `.offcanvas-top` places offcanvas on the top of the viewport
- `.offcanvas-bottom` places offcanvas on the bottom of the viewport
+- `.offcanvas-fullscreen` covers the entire viewport
-Try the top, right, and bottom examples out below.
+Try the top, right, bottom, and fullscreen examples out below.
<Example code={`<button class="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasTop" aria-controls="offcanvasTop">Toggle top offcanvas</button>
</div>
</div>`} />
+<Example code={`<button class="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasFullscreen" aria-controls="offcanvasFullscreen">Toggle fullscreen offcanvas</button>
+
+ <div class="offcanvas offcanvas-fullscreen" tabindex="-1" id="offcanvasFullscreen" aria-labelledby="offcanvasFullscreenLabel">
+ <div class="offcanvas-header">
+ <h5 class="offcanvas-title" id="offcanvasFullscreenLabel">Fullscreen offcanvas</h5>
+ <CloseButton dismiss="offcanvas" />
+ </div>
+ <div class="offcanvas-body">
+ <p>This offcanvas covers the entire viewport, useful for full-page menus or modal-like experiences.</p>
+ </div>
+ </div>`} />
+
+## Footer
+
+Add an optional `.offcanvas-footer` for action buttons or other content at the bottom of the offcanvas.
+
+<Example class="bd-example-offcanvas p-0 bg-body-tertiary overflow-hidden" code={`<div class="offcanvas offcanvas-start show" tabindex="-1" id="offcanvasFooter" aria-labelledby="offcanvasFooterLabel">
+ <div class="offcanvas-header">
+ <h5 class="offcanvas-title" id="offcanvasFooterLabel">Offcanvas with footer</h5>
+ <CloseButton dismiss="offcanvas" />
+ </div>
+ <div class="offcanvas-body">
+ <p>Content for the offcanvas goes here. The footer will stick to the bottom.</p>
+ </div>
+ <div class="offcanvas-footer">
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="offcanvas">Close</button>
+ <button type="button" class="btn btn-primary">Save changes</button>
+ </div>
+ </div>`} />
+
## Accessibility
Since the offcanvas panel is conceptually a modal dialog, be sure to add `aria-labelledby="..."`—referencing the offcanvas title—to `.offcanvas`. Note that you don’t need to add `role="dialog"` since we already add it via JavaScript.
}
}
+ //
+ // Resizable examples
+ //
+
+ .bd-example-resizable {
+ position: relative;
+ }
+
+ .bd-resizable-container {
+ max-width: 100%;
+ padding: 1rem;
+ overflow: hidden;
+ resize: horizontal;
+ background-color: var(--bs-bg-body);
+ border: 1px dashed var(--bs-border-color);
+ @include border-radius(var(--bs-border-radius));
+ }
+
//
// Code snippets
//
export const Example: typeof import('@shortcodes/Example.astro').default
export const JsDismiss: typeof import('@shortcodes/JsDismiss.astro').default
export const JsDocs: typeof import('@shortcodes/JsDocs.astro').default
+ export const NavbarPlacementPlayground: typeof import('@shortcodes/NavbarPlacementPlayground.astro').default
export const Placeholder: typeof import('@shortcodes/Placeholder.astro').default
+ export const ResizableExample: typeof import('@shortcodes/ResizableExample.astro').default
export const ScssDocs: typeof import('@shortcodes/ScssDocs.astro').default
export const StepperPlayground: typeof import('@shortcodes/StepperPlayground.astro').default
export const Swatch: typeof import('@shortcodes/Swatch.astro').default