#javascript #html #sass
Вопрос:
Я новичок в Javascript и пытаюсь создать навигационную панель с подменю, используя ванильный Javascript. Я попытался настроить подменю на отображение / скрытие по щелчку, но я также хотел бы, чтобы подменю скрывалось, когда мы фокусируемся на другом элементе. Я пытался, но не могу этого сделать.
Вот мой код, если вы можете, пожалуйста, взгляните: HTML:
<nav id="navigation" class="main-nav">
<div class="wrapper">
<a href="index.html" class="nav-logo">MAIN LOGO</a>
<div id="sidebarNav" class="sidebar-nav">
<button class="closeBtn" id="closeMenu">
<i class="bi bi-x"></i>
</button>
<ul class="menu">
<li class="menu-item"><a href="index.html" class="menu-link">Home</a></li>
<li class="menu-item"><a href="#" class="menu-link">About</a></li>
<li class="menu-item menu-item-has-children">
<a href="#" class="menu-link">
Dropdown
</a>
<ul class="sub-menu">
<li class="menu-item"><a href="#" class="menu-link">Home Grid</a></li>
<li class="menu-item"><a href="#" class="menu-link">Home Grid 3 col</a></li>
<li class="menu-item"><a href="#" class="menu-link">Home Grid 3 col Full</a></li>
</ul>
</li>
<li class="menu-item"><a href="#" class="menu-link">Contact</a></li>
<li class="menu-item"><a href="#" class="menu-link">Link</a></li><li class="menu-item menu-item-has-children">
<a href="#" class="menu-link">
Dropdown
</a>
<ul class="sub-menu">
<li class="menu-item"><a href="#" class="menu-link">Home Grid</a></li>
<li class="menu-item"><a href="#" class="menu-link">Home Grid 3 col</a></li>
<li class="menu-item"><a href="#" class="menu-link">Home Grid 3 col Full</a></li>
</ul>
</li>
<li class="menu-item"><a href="#" class="menu-link">Blog</a></li>
</ul>
</div>
<button id="toggleSidebar" class="toggle-button">
<i class="bi bi-list"></i>
</button>
</div><!-- .wrapper -->
</nav>
CSS:
.site-header {
width: 100%;
position: relative;
z-index: 999;
.toggle-button {
border: 1px groove rgba(0, 0, 0, 0.1);
padding: 3px 8px;
margin: 8px 0;
text-align: center;
cursor: pointer;
display: none;
i {
font-size: 22px;
}
}
.main-nav {
background: #ddd;
.wrapper {
display: flex;
align-items: center;
justify-content: space-between;
.sidebar-nav {
display: flex;
align-items: center;
justify-content: flex-end;
}
.menu {
display: flex;
align-items: center;
justify-content: space-between;
list-style: none;
padding: 0;
margin: 0;
.menu-item {
list-style: none;
margin: 0;
padding: 0;
a {
padding: 20px 15px;
display: block;
}
}
}
.menu-item {
amp;.menu-item-has-children {
position: relative;
.sub-menu {
position: absolute;
top: 100%;
left: 0;
padding: 0;
margin: 0;
text-align: left;
background: #fff;
border-top: 3px solid green;
min-width: 180px;
line-height: 1;
text-align: left;
z-index: 999;
box-shadow: 0 0 2px 1px rgba(0,0,0,0.2);
display: none;
li {
margin: 0;
padding: 0;
display: block;
border-bottom: 1px solid rgba(189, 188, 188, 0.3);
a {
font-size: .9rem;
font-weight: 400;
line-height: 1.2em;
letter-spacing: 0.6px;
padding: 15px;
text-transform: capitalize;
color: #555555;
}
}
}
}
amp;.active {
.sub-menu {
display: block;
}
}
}
.menu-item-has-children > a::after {
margin-left: .2rem;
vertical-align: 0;
border: none !important;
content: "2193" !important;
font: normal;
font-size: 13px;
font-weight: 900;
color: #333;
}
}
}
}
JS:
function dropdownMenu() {
const submenus = document.querySelectorAll(".menu-item-has-children");
for (var i = 0; i < submenus.length; i ) {
submenus[i].addEventListener("click", function (e) {
e.preventDefault();
e.stopPropagation();
var last = this.closest('ul').querySelector('.active');
if (last amp;amp; last !== this) last.classList.remove("active");
this.classList.toggle("active");
});
}
document.addEventListener("click", function () {
var last = document.querySelector('.main-nav .active');
if (last) last.classList.remove("active");
if (last amp;amp; last ) last.classList.remove("active");
});
}
Выпадающее меню();
Ответ №1:
Попробуйте этот пример. Я добавил в ваш цикл for дополнительные addEventListener
функции для mouseleave
и очистил ненужные строки в файле js.
function dropdownMenu() {
const submenus = document.querySelectorAll('.menu-item-has-children');
for (let i = 0; i < submenus.length; i ) {
submenus[i].addEventListener('click', function (e) {
e.stopPropagation();
const last = this.closest('ul').querySelector('.active');
if (last amp;amp; last !== this) last.classList.remove('active');
this.classList.toggle('active');
});
// Added lines
submenus[i].addEventListener('focusout', function () {
const last = document.querySelector('.main-nav .active');
if (last) last.classList.remove('active');
});
//===
}
}
dropdownMenu();
.site-header {
width: 100%;
position: relative;
z-index: 999;
}
.toggle-button {
border: 1px groove rgba(0, 0, 0, 0.1);
padding: 3px 8px;
margin: 8px 0;
text-align: center;
cursor: pointer;
display: none;
}
.toggle-button i {
font-size: 22px;
}
.main-nav {
background: #ddd;
}
.wrapper {
display: flex;
align-items: center;
justify-content: space-between;
}
.sidebar-nav {
display: flex;
align-items: center;
justify-content: flex-end;
}
.menu {
display: flex;
align-items: center;
justify-content: space-between;
list-style: none;
padding: 0;
margin: 0;
}
.menu-item {
list-style: none;
margin: 0;
padding: 0;
}
.menu-item a {
padding: 20px 15px;
display: block;
}
.menu-item.menu-item-has-children {
position: relative;
}
.sub-menu {
position: absolute;
top: 100%;
left: 0;
padding: 0;
margin: 0;
text-align: left;
background: #fff;
border-top: 3px solid green;
min-width: 180px;
line-height: 1;
text-align: left;
z-index: 999;
box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.2);
display: none;
}
.sub-menu li {
margin: 0;
padding: 0;
display: block;
border-bottom: 1px solid rgba(189, 188, 188, 0.3);
}
.sub-menu a {
font-size: 0.9rem;
font-weight: 400;
line-height: 1.2em;
letter-spacing: 0.6px;
padding: 15px;
text-transform: capitalize;
color: #555555;
}
.menu-item-has-children.active .sub-menu {
display: block;
}
.menu-item-has-children > a::after {
margin-left: 0.2rem;
vertical-align: 0;
border: none !important;
content: '2193' !important;
font: normal;
font-size: 13px;
font-weight: 900;
color: #333;
}
<nav id="navigation" class="main-nav">
<div class="wrapper">
<a href="index.html" class="nav-logo">MAIN LOGO</a>
<div id="sidebarNav" class="sidebar-nav">
<button class="closeBtn" id="closeMenu">
<i class="bi bi-x"></i>
</button>
<ul class="menu">
<li class="menu-item">
<a href="index.html" class="menu-link">Home</a>
</li>
<li class="menu-item"><a href="#" class="menu-link">About</a></li>
<li class="menu-item menu-item-has-children">
<a href="#" class="menu-link"> Dropdown </a>
<ul class="sub-menu">
<li class="menu-item">
<a href="#" class="menu-link">Home Grid</a>
</li>
<li class="menu-item">
<a href="#" class="menu-link">Home Grid 3 col</a>
</li>
<li class="menu-item">
<a href="#" class="menu-link">Home Grid 3 col Full</a>
</li>
</ul>
</li>
<li class="menu-item"><a href="#" class="menu-link">Contact</a></li>
<li class="menu-item"><a href="#" class="menu-link">Link</a></li>
<li class="menu-item menu-item-has-children">
<a href="#" class="menu-link"> Dropdown </a>
<ul class="sub-menu">
<li class="menu-item">
<a href="#" class="menu-link">Home Grid</a>
</li>
<li class="menu-item">
<a href="#" class="menu-link">Home Grid 3 col</a>
</li>
<li class="menu-item">
<a href="#" class="menu-link">Home Grid 3 col Full</a>
</li>
</ul>
</li>
<li class="menu-item"><a href="#" class="menu-link">Blog</a></li>
</ul>
</div>
<button id="toggleSidebar" class="toggle-button">
<i class="bi bi-list"></i>
</button>
</div>
</nav>
Комментарии:
1. Mouseleave закрывает подменю при событии мыши. Но, исходя из вашей идеи, я попытался использовать дочерние элементы, и это сработало. Проверьте код ниже. Надеюсь, я прав.
var submenuList = submenus[i].querySelector(".sub-menu"); submenuList.lastElementChild.addEventListener('focusout', function () { const last = document.querySelector('.main-nav .active'); if (last) last.classList.remove('active'); });
Спасибо @ЖнецЪ2. Да, вы можете использовать
focusout
для потери фокуса элемента. Я обновил обзор кода и очистил js.