Found this navigation + JS tutorial here: How to Build a Responsive Navigation Bar with a Dropdown Menu using JavaScript
This particular line of code does not do what it is supposed to be doing:
//close dropdown menu when you click on the document body
document.documentElement.addEventListener(“click”, (e) => {
closeDropdownMenu();
setAriaExpandedFalse();
});
To be specific, the navigation functions seize to work when that code is added.
Thanks in advance!
Can you provide us a link to your “working” version of this menu?
js
const dropdownBtn = document.querySelectorAll(".dropdown-btn");
const dropdown = document.querySelectorAll(".dropdown");
const hamburgerBtn = document.getElementById("hamburger");
const navMenu = document.querySelector(".menu");
const links = document.querySelectorAll(".dropdown a");
function setAriaExpandedFalse() {
dropdownBtn.forEach((btn) => btn.setAttribute("aria-expanded", "false"));
}
function closeDropdownMenu() {
dropdown.forEach((drop) => {
drop.classList.remove("active");
drop.addEventListener("click", (e) => e.stopPropagation());
});
}
function toggleHamburger() {
navMenu.classList.toggle("show");
}
//dropdown buttons are clicked and collapses
dropdownBtn.forEach((btn) => {
btn.addEventListener("click", function (e) {
const dropdownIndex = e.currentTarget.dataset.dropdown;
const dropdownElement = document.getElementById(dropdownIndex);
dropdownElement.classList.toggle("active");
dropdown.forEach((drop) => {
if (drop.id !== btn.dataset["dropdown"]) {
drop.classList.remove("active");
}
});
e.stopPropagation;
btn.setAttribute(
"aria-expanded",
btn.getAttribute("aria-expanded") === "false" ? "true" : "false"
);
});
});
// close dropdown menu when the dropdown links are clicked
links.forEach((link) =>
link.addEventListener("click", () => {
closeDropdownMenu();
setAriaExpandedFalse();
})
);
//close dropdown when the escape key is pressed
document.addEventListener("keydown", (e) => {
if (e.key === "Escape") {
closeDropdownMenu();
setAriaExpandedFalse();
}
});
//close dropdown menu when you click on the document body
document.documentElement.addEventListener("click", () => {
closeDropdownMenu();
setAriaExpandedFalse();
});
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./style.css" />
<link
href="https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css"
rel="stylesheet"
/>
<title>HTML CSS Practice</title>
</head>
<body>
<header id="nav-menu" aria-label="navigation bar">
<div class="container">
<div class="nav-start">
<a href="/" class="logo">
<img
src="https://github.com/Evavic44/responsive-navbar-with-dropdown/blob/main/assets/images/logo.png?raw=true"
width="35"
height="35"
alt="Inc Logo"
/>
</a>
<nav class="menu">
<ul class="menu-bar">
<li>
<button
class="nav-link dropdown-btn"
data-dropdown="dropdown1"
aria-haspopup="true"
aria-expanded="false"
aria-label="browse"
>
Browse
<i class="bx bx-chevron-down" aria-hidden="true"></i>
</button>
<div id="dropdown1" class="dropdown">
<ul role="menu">
<li role="menuitem">
<a href="#best-of-the-day" class="dropdown-link">
<img src="./assets/icons/botd.svg" class="icon" />
<div>
<span class="dropdown-link-title"
>Best of the day</span
>
<p>Shorts featured today by curators</p>
</div>
</a>
</li>
<li role="menuitem">
<a href="#subscriptions" class="dropdown-link">
<img src="./assets/icons/sp.svg" class="icon" />
<div>
<span class="dropdown-link-title">Subscriptions</span>
<p>Gain exclusive access</p>
</div>
</a>
</li>
<li role="menuitem">
<a href="#creative-feed" class="dropdown-link">
<img src="./assets/icons/cf.svg" class="icon" />
<div>
<span class="dropdwon-link-title">Creative Feed</span>
<p>See trending creations</p>
</div>
</a>
</li>
</ul>
<ul role="menu">
<li class="dropdown-title">
<span class="dropdown-link-title">Browse by apps</span>
</li>
<li role="menuitem">
<a class="dropdown-link" href="#adobe-xd">
<img src="./assets/icons/xd.svg" />
Adobe XD
</a>
</li>
<li role="menuitem">
<a class="dropdown-link" href="#after-effect">
<img src="./assets/icons/ae.svg" />
After Effect
</a>
</li>
<li role="menuitem">
<a class="dropdown-link" href="#sketch">
<img src="./assets/icons/sketch.svg" />
Sketch
</a>
</li>
<li role="menuitem">
<a class="dropdown-link" href="#indesign">
<img src="./assets/icons/indesign.svg" />
Indesign
</a>
</li>
<li role="menuitem">
<a class="dropdown-link" href="#figma">
<img src="./assets/icons/figma.svg" />
Figma
</a>
</li>
</ul>
</div>
</li>
<li>
<!-- https://www.freecodecamp.org/news/how-to-build-a-responsive-navigation-bar-with-dropdown-menu-using-javascript/ -->
<button
class="nav-link dropdown-btn"
data-dropdown="dropdown2"
aria-haspopup="true"
aria-expanded="false"
aria-label="discover"
>
Discover <i class="bx bx-chevron-down" aria-hidden="true"></i>
</button>
<div id="dropdown2" class="dropdown">
<ul role="menu">
<li>
<span class="dropdown-link-title">Browse Categories</span>
</li>
<li role="menuitem">
<a class="dropdown-link" href="#branding">Branding</a>
</li>
<li role="menuitem">
<a class="dropdown-link" href="#illustrations"
>Illustration</a
>
</li>
</ul>
<ul role="menu">
<li>
<span class="dropdown-link-title">Download App</span>
</li>
<li role="menuitem">
<a class="dropdown-link" href="#mac-windows"
>MacOS & Windows</a
>
</li>
<li role="menuitem">
<a class="dropdown-link" href="#linux">Linux</a>
</li>
</ul>
</div>
</li>
<li><a href="/" class="nav-link">Jobs</a></li>
<li><a href="/" class="nav-link">Livestream</a></li>
<li><a href="/" class="nav-link">About</a></li>
</ul>
</nav>
</div>
<div class="nav-end">
<div class="right-container">
<form action="" role="search" class="search">
<input type="search" name="search" placeholder="Search" />
<i class="bx bx-search search-icon" aria-hidden="tr"></i>
</form>
<a href="#profile">
<img
src="https://github.com/Evavic44/responsive-navbar-with-dropdown/blob/main/assets/images/user.jpg?raw=true"
width="30"
height="30"
alt="user image"
/>
</a>
<button class="btn btn-primary">Create</button>
</div>
<button
id="hamburger"
aria-label="hamburger"
aria-haspopup="true"
aria-expanded="false"
>
<i class="bx bx-menu" aria-hidden="true"></i>
</button>
</div>
</div>
</header>
</body>
<script src="./script.js"></script>
</html>
Can you provide the CSS too?
Also, can you be very specific about what doesn’t work?
Here is the CSS, the code was supposed to perform this action:
//close dropdown menu when you click on the document body
all other else worked, other than this code here
//close dropdown menu when you click on the document body
document.documentElement.addEventListener(“click”, () => {
closeDropdownMenu();
setAriaExpandedFalse();
});
Thank you!
Clicking on the body of the page while a dropdown menu is active supposed to close the dropdown menu
lemon05:
Here is the CSS
I’m not seeing it. Can you paste it in here like you did for the JS and HTML.
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@200;300;400;500;600;700&display=swap");
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Inter", sans-serif;
}
:root {
--dark-grey: #333333;
--medium-grey: #636363;
--light-grey: #eeeeee;
--ash: #f4f4f4;
--primary-color: #2b72fb;
--white: white;
--border: 1px solid var (--light);
--shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,
rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;
}
body {
font-family: inherit;
background-color: var(--white);
color: var(--dark-grey);
letter-spacing: -0.4px;
}
ul {
list-style: none;
}
a {
text-decoration: none;
color: inherit;
}
button {
border: none;
background-color: transparent;
cursor: pointer;
color: inherit;
}
.btn {
display: block;
background-color: var(--primary-color);
color: var(--white);
text-align: center;
padding: 0.6rem 1.4rem;
font-size: 1rem;
font-weight: 500;
border-radius: 5px;
}
.icon {
padding: 0.5rem;
background-color: var(--light-grey);
border-radius: 10px;
}
.logo {
margin-right: 1.5rem;
}
#nav-menu {
border-bottom: var(--border);
}
.container {
display: flex;
align-items: center;
justify-content: space-between;
max-width: 1600px;
margin: 0 auto;
column-gap: 2rem;
height: 90px;
padding: 1.2rem 3rem;
}
.menu {
position: relative;
background: var(--white);
}
.menu-bar li:first-child .dropdown {
flex-direction: initial;
min-width: 480px;
}
.menu-bar li:first-child ul:nth-child(1) {
border-right: var(--border);
}
.menu-bar .dropdown-link-title {
font-weight: 600;
}
.menu-bar .nav-link {
font-size: 1rem;
font-weight: 500;
letter-spacing: -0.6px;
padding: 0.3rem;
margin: 0 0.6rem;
}
.menu-bar .nav-link:hover,
.dropdown-link:hover {
color: var(--primary-color);
}
.nav-start,
.nav-end,
.menu-bar,
.right-container,
.right-container .search {
display: flex;
align-items: center;
}
.dropdown {
display: flex;
flex-direction: column;
min-width: 230px;
background-color: var(--white);
border-radius: 10px;
position: absolute;
top: 36px;
z-index: 1;
visibility: hidden;
opacity: 0;
transform: scale(0.97) translateX(-5px);
box-shadow: var(--shadow);
}
.dropdown.active {
visibility: visible;
opacity: 1;
transform: scale(1) translateX(5px);
}
.dropdown ul {
display: flex;
flex-direction: column;
gap: 0.5rem;
padding: 1.2rem;
font-size: 0.95rem;
}
.dropdown-link {
display: flex;
gap: 0.5rem;
padding: 0.5rem 0;
border-radius: 7px;
transition: 0.1s ease-in-out;
}
.dropdown-link p {
font-size: 0.8rem;
color: var(--medium-grey);
}
.right-container {
display: flex;
align-items: center;
column-gap: 1rem;
}
.right-container .search {
position: relative;
}
.right-container img {
border-radius: 50%;
}
.search input {
background-color: var(--ash);
border: none;
border-radius: 6px;
padding: 0.7rem;
padding-left: 2.4rem;
font-size: 16px;
width: 100%;
border: var(--border);
}
.search .search-icon {
position: absolute;
left: 10px;
top: 50%;
transform: translateY(-50%);
opacity: 0.6;
}
#hamburger {
display: none;
padding: 0.1rem;
margin-left: 1rem;
font-size: 1.9rem;
}
@media (max-width: 1100px) {
#hamburger {
display: block;
}
.container {
padding: 1.2rem;
}
.menu {
display: none;
position: absolute;
top: 87px;
left: 0;
min-height: 100vh;
width: 100vw;
}
.menu-bar li:first-child ul:nth-child(1) {
border-right: none;
border-bottom: var(--border);
}
.dropdown {
display: none;
min-width: 100%;
border: none !important;
border-radius: 5px;
position: static;
top: 0;
left: 0;
visibility: visible;
opacity: 1;
transform: none;
box-shadow: none;
}
.menu.show,
.dropdown.active {
display: block;
}
.dropdown ul {
padding-left: 0.3rem;
}
.menu-bar {
display: flex;
flex-direction: column;
align-items: stretch;
row-gap: 1rem;
padding: 1rem;
}
.menu-bar .nav-link {
display: flex;
justify-content: space-around;
width: 100%;
font-weight: 600;
font-size: 1.2rem;
margin: 0;
}
.menu-bar > li:not(:last-child) {
padding-bottom: 0.5rem;
border-bottom: var(--border);
}
}
@media (max-width: 600px) {
.right-container {
display: none;
}
}
Thank you for your patience
That click handler on the documentElement is being called immediately after the click handler on the dropdown button. You can add console.logs to each handler to verify this. The click handler on the documentElement is calling closeDropdownMenu()
which thus immediately closes the dropdown menu you just tried to open. So that’s why it appears that none of the dropdown buttons are working when you add that handler.
Yes, I can confirm that is the case. Can I have a useful tip I could use to resolve this?
I solved it by checking if the click target is in the menu. Only if it is not then the handler should go ahead and call closeDropdownMenu()
and setAriaExpandedFalse()
.
This method might come in handy:
Node: contains() method
1 Like
Thank you! Will try this out!
system
Closed
December 7, 2023, 5:13am
14
This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.