I have a Bootstrap navbar menu, and I'm trying to wrap overflowing menu items in a dropdown if there's not enough avaliable space. I have this solution - it works perfectly and does what I'm looking for:
const contentBar = document.querySelector(".context-bar")
const dropdown = document.querySelector(".grouped-content")
const update = () => {
const offsetTop = contentBar.offsetTop
dropdown.innerHTML = ""
document.querySelectorAll(".context-bar > a").forEach((item) => {
if (item.offsetTop > offsetTop) {
let li = document.createElement("li")
li.innerHTML += item.outerHTML
dropdown.appendChild(li)
}
})
}
update()
window.addEventListener("resize", update)
.link-bar {
display: flex;
position: relative;
background: #ddd;
padding: 0 10px;
color: #000;
width: 100%;
box-sizing: border-box;
}
.context-bar {
flex: 1;
height: 60px;
overflow: hidden;
}
.context-bar-link, .grouped-link {
color: #000;
display: inline-block;
white-space: nowrap;
max-width: 18rem;
text-overflow: ellipsis;
overflow: hidden;
padding: 20px 10px;
}
.grouped-content {
display: none;
list-style-type: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
right: 10px;
max-height: 200px;
overflow-y: auto;
}
.grouped:hover .grouped-content {
display: block;
}
body {
padding-top: 50px;
}
a {
text-decoration: none;
}
<div class="container">
<nav class="link-bar">
<div class="context-bar">
<a href="#" class="context-bar-link">Item 1</a>
<a href="#" class="context-bar-link">Item 22</a>
<a href="#" class="context-bar-link">Item 333</a>
<a href="#" class="context-bar-link">Item 4444</a>
<a href="#" class="context-bar-link">Item 5555555</a>
<a href="#" class="context-bar-link">Item 66</a>
<a href="#" class="context-bar-link">Item 7777777777777</a>
<a href="#" class="context-bar-link">Item 8</a>
<a href="#" class="context-bar-link">Item 999999</a>
<a href="#" class="context-bar-link">Item 10101010</a>
<a href="#" class="context-bar-link">Item 1111</a>
<a href="#" class="context-bar-link">Item 12121212</a>
<a href="#" class="context-bar-link">Item 1313131313131</a>
<a href="#" class="context-bar-link">Item 1414</a>
<a href="#" class="context-bar-link">Item 15</a>
<a href="#" class="context-bar-link">Item 16161616</a>
<a href="#" class="context-bar-link">Item 1717</a>
<a href="#" class="context-bar-link">Item 18181818181818</a>
<a href="#" class="context-bar-link">Item 191919</a>
<a href="#" class="context-bar-link">Item 20</a>
<a href="#" class="context-bar-link">Item 212121</a>
<a href="#" class="context-bar-link">Item 2222</a>
</div>
<div class="grouped">
<a href="#" class="grouped-link">More</a>
<ul class="grouped-content"></ul>
</div>
</nav>
</div>
However, it doesn't woth with Bootstrap's navbar - probably because we can't check for offsetTop
? How can I change the script to work with the Bootstrap navbar?
This is what I have:
const contentBar = document.querySelector(".context-bar")
const dropdown = document.querySelector(".grouped-content")
const update = () => {
const offsetTop = contentBar.offsetTop
dropdown.innerHTML = ""
document.querySelectorAll(".context-bar > li").forEach((item) => {
if (item.offsetTop > offsetTop) {
let li = document.createElement("li")
li.innerHTML += item.outerHTML
dropdown.appendChild(li)
}
})
}
update()
window.addEventListener("resize", update)
.context-bar {
flex: 1;
height: 60px;
overflow: hidden;
}
.nav-link,
.grouped-link {
color: #000;
display: inline-block;
white-space: nowrap;
max-width: 18rem;
text-overflow: ellipsis;
overflow: hidden;
padding: 20px 10px;
}
.grouped-content {
display: none;
list-style-type: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
right: 10px;
max-height: 200px;
overflow-y: auto;
}
.grouped:hover .grouped-content {
display: block;
}
body {
padding-top: 50px;
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
<nav class="navbar navbar-expand-sm link-bar">
<ul class="navbar-nav context-bar">
<li class="nav-item"><a href="#" class="nav-link">Item 1</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 22</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 333</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 4444</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 5555555</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 66</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 7777777777777</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 8</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 999999</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 10101010</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 1111</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 12121212</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 1313131313131</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 1414</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 15</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 16161616</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 1717</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 18181818181818</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 191919</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 20</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 212121</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 2222</a></li>
<li class="grouped">
<a href="#" class="grouped-link">More</a>
<ul class="grouped-content"></ul>
</li>
</ul>
</nav>
</div>
You need to active the wrapping and the "grouped" element need to be outside the list.
const contentBar = document.querySelector(".context-bar")
const dropdown = document.querySelector(".grouped-content")
const update = () => {
const offsetTop = contentBar.offsetTop
dropdown.innerHTML = ""
document.querySelectorAll(".context-bar > li").forEach((item) => {
if (item.offsetTop > offsetTop) {
let li = document.createElement("li")
li.innerHTML += item.outerHTML
dropdown.appendChild(li)
}
})
}
update()
window.addEventListener("resize", update)
.context-bar {
flex: 1;
height: 40px; /* not 60px */
overflow: hidden;
flex-wrap: wrap; /* added this*/
}
.nav-link,
.grouped-link {
color: #000;
display: inline-block;
white-space: nowrap;
max-width: 18rem;
text-overflow: ellipsis;
overflow: hidden;
padding: 20px 10px;
}
.grouped-content {
display: none;
list-style-type: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
right: 10px;
max-height: 200px;
overflow-y: auto;
}
.grouped:hover .grouped-content {
display: block;
}
body {
padding-top: 50px;
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
<nav class="navbar navbar-expand-sm link-bar">
<ul class="navbar-nav context-bar">
<li class="nav-item"><a href="#" class="nav-link">Item 1</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 22</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 333</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 4444</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 5555555</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 66</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 7777777777777</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 8</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 999999</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 10101010</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 1111</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 12121212</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 1313131313131</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 1414</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 15</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 16161616</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 1717</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 18181818181818</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 191919</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 20</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 212121</a></li>
<li class="nav-item"><a href="#" class="nav-link">Item 2222</a></li>
</ul>
<div class="grouped">
<a href="#" class="grouped-link">More</a>
<ul class="grouped-content"></ul>
</div>
</nav>
</div>