I’m trying to create a multi-level dropdown menu using Bootstrap. By default, the dropdowns should align to the right side, but if there’s not enough space, they should switch to align to the left.
The problem I’m facing is that the inner dropdown menus sometimes extend beyond the right side of the screen, especially when there’s not enough space.
Here’s the relevant code:
HTML and CSS:
$(document).ready(function() {
$('.nav-item.dropdown').on('mouseenter', function() {
var $dropdownMenu = $(this).find('.dropdown-menu');
var rect = $dropdownMenu[0].getBoundingClientRect();
if (rect.right > window.innerWidth) {
$dropdownMenu.addClass('dropdown-menu-end');
} else {
$dropdownMenu.removeClass('dropdown-menu-end');
}
});
});
<style>body {
font-family: Verdana, Geneva, Tahoma, sans-serif;
}
.navbar {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
padding: 10px;
background-color: dimgrey;
width: 100%;
}
.navbar-top {
display: flex;
justify-content: space-between;
width: 100%;
align-items: center;
}
.navbar-left {
display: flex;
align-items: center;
}
.navbar-brand {
margin-right: 20px;
}
.switch-role-form {
display: flex;
align-items: center;
}
.switch-role {
margin-right: 10px;
}
.welcome-message {
color: blue;
text-align: right;
}
.logout-button {
top: 10px;
right: 10px;
}
.navbar-nav {
display: flex;
justify-content: center;
width: 100%;
background-color: palevioletred;
}
.dropdown-menu li {
position: relative;
}
.dropdown-menu .dropdown-submenu {
display: none;
position: absolute;
left: 100%;
top: -7px;
}
.dropdown-submenu-left {
right: 100%;
left: auto;
}
.dropdown-menu>li:hover>.dropdown-submenu {
display: block;
}
.nav-item:hover>.dropdown-menu {
display: block;
}
.dropdown-submenu:hover>.dropdown-menu {
display: block;
}
.navbar-expand-lg {
width: 100%;
display: flex;
justify-content: center;
}
.dropdown-menu-end {
left: auto;
right: 100%;
}
</style>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dropdown Menu Alignment</title>
<style>
/* Add your CSS here */
</style>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
</head>
<body>
<div class="navbar">
<nav class="navbar navbar-expand-lg bg-body-tertiary">
<div class="container-fluid">
<ul class="navbar-nav">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Menu Item
</a>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item" href="#">Submenu Item »</a>
<ul class="dropdown-menu dropdown-submenu">
<li><a class="dropdown-item" href="#">Submenu Item 1</a></li>
<li><a class="dropdown-item" href="#">Submenu Item 2</a></li>
</ul>
</li>
<li><a class="dropdown-item" href="#">Another Item</a></li>
</ul>
</li>
</ul>
</div>
</nav>
</div>
</body>
2
Answers
You need to override
.dropdown-menu[data-bs-popper]
classcss
fromleft: 0;
toright:0;
as below:Your js code of
rect.right
do not include thedropdown-submenu
element. So, you can try this code as below, to calculate the right boundary of thedropdown-submenu
element and add or remove the classdropdown-menu-end
:Then change the css class
.dropdown-menu-end
as below:Before:
1![enter image description here](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%200%200'%3E%3C/svg%3E)
2![enter image description here](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%200%200'%3E%3C/svg%3E)
After:
1![enter image description here](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%200%200'%3E%3C/svg%3E)
2![enter image description here](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%200%200'%3E%3C/svg%3E)