Nav overflow
Automatically collapse navigation items into a "More" menu when space is limited using the Priority+ pattern.
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 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:
- Wrap the
.navin a.nav-overflowelement and adddata-cx-toggle="nav-overflow"to that wrapper. - The wrapper is what makes this reliable. Collapsing items changes the width of the nav, so the component measures the wrapper instead. Measuring the nav would feed the result back in as the input.
- Responds to container size, not viewport size. The component watches the wrapper with a ResizeObserver, so it works perfectly in embedded contexts, documentation examples, and responsive containers.
- Overflow items are cloned into a "More" 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.
Chassis CSS respects user accessibility preferences by automatically disabling animations when the prefers-reduced-motion media query is detected. See the reduced motion guidelines in our accessibility documentation for implementation details.
Examples
Wrap the nav in <div class="nav-overflow" data-cx-toggle="nav-overflow">. When items don't fit, they'll automatically move to a "More" menu. Drag the right edge of the container below to see how nav items automatically move to the "More" menu as space becomes limited.
<div class="nav-overflow" data-cx-toggle="nav-overflow">
<ul class="nav nav-pills">
<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>
</div>With tabs
The overflow pattern works seamlessly with tabbed navigation:
<div class="nav-overflow" data-cx-toggle="nav-overflow">
<ul class="nav nav-tabs">
<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>
</div>With underline
<div class="nav-overflow" data-cx-toggle="nav-overflow">
<ul class="nav nav-underline">
<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>
</div>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.
<div class="nav-overflow" data-cx-toggle="nav-overflow">
<ul class="nav nav-pills">
<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>
</div>With disabled items
Disabled states are preserved when items move to the overflow menu:
<div class="nav-overflow" data-cx-toggle="nav-overflow">
<ul class="nav nav-pills">
<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>
</div>In a navbar
The nav overflow pattern can also be used within a navbar for horizontal navigation that adapts to available space:
<nav class="navbar navbar-expand bg-body-tertiary" aria-label="Main navigation">
<div class="container fluid">
<a class="navbar-brand" href="#">Brand</a>
<div class="nav-overflow" data-cx-toggle="nav-overflow">
<ul class="nav 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" href="#">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Contact</a>
</li>
</ul>
</div>
</div>
</nav>Customizing the toggle
Custom text
Use the moreText option to customize the text shown in the overflow toggle button:
const nav = document.querySelector('.nav-overflow')
new chassis.NavOverflow(nav, {
moreText: 'See all'
})Custom icon
Provide a custom icon via the moreIcon option. Any HTML string works, including inline SVGs:
const nav = document.querySelector('.nav-overflow')
new chassis.NavOverflow(nav, {
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>',
moreText: false // Icon-only toggle; falls back to an aria-label of "More"
})Alternatively, place an element with data-cx-overflow-icon directly inside the nav. The component will pick it up, use it as the toggle icon, and remove the original element from the DOM. This takes priority over the moreIcon option.
<div class="nav-overflow" data-cx-toggle="nav-overflow">
<ul class="nav nav-pills">
<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>
<svg data-cx-overflow-icon xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
<path d="M8 4.754a3.246 3.246 0 1 0 0 6.492 3.246 3.246 0 0 0 0-6.492"/>
</svg>
</ul>
</div>Icon placement
Use the iconPlacement option to position the icon before ('start', the default) or after ('end') the text:
const nav = document.querySelector('.nav-overflow')
new chassis.NavOverflow(nav, {
moreText: 'Menu',
iconPlacement: 'end'
})Minimum visible items
Use the threshold option to ensure a minimum number of items remain visible before the overflow kicks in:
const nav = document.querySelector('.nav-overflow')
new chassis.NavOverflow(nav, {
threshold: 3 // Always keep at least 3 items visible
})Collapse all
Use the collapseBelow option to force all items into the overflow dropdown when the wrapper's width is below a threshold. Pass a breakpoint name to resolve the value from --cx-breakpoint-{name}, or a number for a direct pixel value.
<div class="nav-overflow" data-cx-toggle="nav-overflow" data-cx-collapse-below="md">
<ul class="nav nav-pills">
<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>
</ul>
</div>Or via JavaScript with a raw pixel value:
const nav = document.querySelector('.nav-overflow')
new chassis.NavOverflow(nav, {
collapseBelow: 768
})Above the threshold, normal progressive collapse resumes. Items with .nav-overflow-keep are never collapsed.
Usage
Via data attributes
Wrap the .nav in a .nav-overflow element and add data-cx-toggle="nav-overflow" to that wrapper to automatically enable the overflow behavior.
| Attribute | Description |
|---|---|
data-cx-toggle="nav-overflow" | Enables responsive overflow handling on the .nav-overflow wrapper. |
<div class="nav-overflow" data-cx-toggle="nav-overflow">
<ul class="nav nav-pills">
<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>
</div>Via JavaScript
Initialize the nav overflow component manually on the wrapper:
const wrapperElement = document.querySelector('.nav-overflow')
const navOverflow = new chassis.NavOverflow(wrapperElement, {
moreText: 'More',
threshold: 2
})Options
Options are set via data-cx-* attributes or passed to the constructor as an object. Attribute names use the kebab-case form of the option name — data-cx-custom-class, not data-cx-customClass. Attribute values are parsed to their native types:"true" → true, "0" → 0, and valid JSON strings to objects.
Use data-cx-config to pass multiple options as a JSON string:data-cx-config='{"delay":200}'. Individual data-cx-* attributes take precedence over data-cx-config. You can also use JSON values in individual attributes, such as data-cx-delay='{"show":100,"hide":200}'.
When initializing components, Chassis merges configurations from multiple sources in this priority order: default settings, data-cx-config values, individual data-cx-*attributes, and finally any JavaScript object options. Values defined later in this sequence override earlier ones.
| Name | Type | Default | Description |
|---|---|---|---|
collapseBelow | number|string | 0 | Width threshold below which all items collapse into the overflow dropdown. Pass a breakpoint name (e.g., 'md') to resolve from --cx-breakpoint-{name}, or a number for a direct pixel value. 0 disables. |
iconPlacement | string | 'start' | Position of the icon relative to the text in the toggle button. Use 'start' for before the text or 'end' for after. |
menuPlacement | string | 'bottom-end' | Placement of the overflow dropdown menu, passed as data-cx-placement to the menu toggle. |
moreText | string|boolean | 'More' | Text label for the overflow toggle button. Pass false for an icon-only toggle; the button falls back to aria-label="More" so it keeps an accessible name. |
moreIcon | string | '<svg>...</svg>' | SVG or HTML icon for the overflow toggle button. Overridden by a child element with data-cx-overflow-icon if present. |
threshold | number | 0 | Minimum number of items to keep visible before showing overflow. |
Methods
All Chassis CSS component methods are asynchronous and initiate CSS transitions. Methods return immediately when the transition begins, not when it completes. Calling methods on components that are already transitioning will be ignored to prevent conflicts. Learn more about Chassis JavaScript patterns.
You can create a nav overflow instance with the constructor:
const navOverflow = new chassis.NavOverflow('#myNav', {
threshold: 2
})| 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. |
Events
Chassis CSS's nav overflow component exposes events for hooking into overflow functionality.
| Event type | Description |
|---|---|
update.cx.navoverflow | Fired when the overflow calculation is updated (on resize or manual update). |
overflow.cx.navoverflow | Fired when items are moved to the overflow menu. Event includes overflowCount and visibleCount properties. |
const myNav = document.getElementById('myNav')
myNav.addEventListener('overflow.cx.navoverflow', event => {
console.log(`${event.overflowCount} items moved to overflow`)
console.log(`${event.visibleCount} items still visible`)
})