I created a sidebar toggle and also gave background opacity but when I click another area or when closed the sidebar the background opacity didn't close. when I click the button the dropdown-content show and the background-opacity show but when I click again on the button the dropdown content closed but the background opacity does not close. How I did it. Please help me. I gave the code below. If someone can help me it will be very helpful for me. I try so many times but in the end, I can't do it. 😥
function toggleDropDown(id) {
document.querySelectorAll('.dropdown-content').forEach(el => el.id === id ? el.classList.toggle('show') : el.classList.remove("show"));
document.body.style.backgroundColor = "rgba(0,0,0,0.4)";
}
document.addEventListener('click', (e) => {
// cases where we want to close the dropdown
if (e.target.closest(".dropdown") === null) {
document.querySelectorAll('.dropdown-content').forEach(el => el.classList.remove("show"));
}
});
*{margin:0;padding:0;}
.dropdown-content{
position: fixed;
width: 30%;
height:100%;
background-color: rgb(255,0,0);
margin-left: 20%;
top:0;
display:none;
z-index:100;
}
.dropbtn{width:20%}
.show{display:block;}
<div class="dropdown">
<button class="dropbtn" onclick="toggleDropDown('openContent')">open</button>
<div class="dropdown-content" id="openContent">Hello, Div</div>
</div>
<h1>Hello World, Heading 1</h1>
First, I would suggest to create a variable that keeps track of the current state of dropdown – which is either true or false.
Plus, I don’t see the benefit in using document.querySelectorAll and having to loop over every element, when you could just directly get the element by addressing its id (openContent)... unless you would want to reuse the function for other cases?
As you are also listening on a click event on the document, we have to watch out for event bubbling by calling e.stopPropagation. In the case of the button for example, this means that we only fire the event for the button but not for the document. Since the button is a child of the document, it would otherwise detect a click event for both and fire twice.
const dropdownContent = document.getElementById("openContent");
let dropDownVisible = false;
function toggleDropDown(e) {
// we need this to prevent the event bubbling from the dropdown button to the document
e.stopPropagation();
// set the dropDownVisible state to the opposite it has been before
dropDownVisible = !dropDownVisible;
if (dropDownVisible) {
dropdownContent.classList.add("show");
document.body.classList.add("bgcolor");
} else {
dropdownContent.classList.remove("show");
document.body.classList.remove("bgcolor");
}
}
// we need this to prevent the event bubbling from the dropdown to the document
dropdownContent.addEventListener("click", (e) => {
e.stopPropagation();
});
// listen for click events on the document
document.addEventListener("click", (e) => {
// -> if the dropdown is visible, toggle its state
dropDownVisible && toggleDropDown(e);
});
* {
margin: 0;
padding: 0;
}
.dropdown-content {
position: fixed;
width: 30%;
height: 100%;
background-color: rgb(255, 0, 0);
margin-left: 20%;
top: 0;
display: none;
z-index: 100;
}
.dropbtn {
width: 20%;
}
.show {
display: block;
}
.bgcolor {
background-color: rgba(0, 0, 0, 0.4);
}
<body>
<div class="dropdown">
<button class="dropbtn" onclick="toggleDropDown(event)">
open
</button>
<div class="dropdown-content" id="openContent">Hello, Div</div>
</div>
<h1>Hello World, Heading 1</h1>
</body>
You will have to remove also the "body" background.
document.body.style.backgroundColor = "initial";
function toggleDropDown(id) {
document.querySelectorAll('.dropdown-content').forEach(el => el.id === id ? el.classList.toggle('show') : el.classList.remove("show"));
document.body.style.backgroundColor = "rgba(0,0,0,0.4)";
}
document.addEventListener('click', (e) => {
// cases where we want to close the dropdown
if (e.target.closest(".dropdown") === null) {
document.querySelectorAll('.dropdown-content').forEach(el => el.classList.remove("show"));
document.body.style.backgroundColor = "initial";
}
});
*{margin:0;padding:0;}
.dropdown-content{
position: fixed;
width: 30%;
height:100%;
background-color: rgb(255,0,0);
margin-left: 20%;
top:0;
display:none;
z-index:100;
}
.dropbtn{width:20%}
.show{display:block;}
<div class="dropdown">
<button class="dropbtn" onclick="toggleDropDown('openContent')">open</button>
<div class="dropdown-content" id="openContent">Hello, Div</div>
</div>
<h1>Hello World, Heading 1</h1>
Add class to body document.body.classList.add('bgcolor'); and remove after close the dropdown
function toggleDropDown(id) {
document.querySelectorAll('.dropdown-content').forEach(el => el.id === id ? el.classList.toggle('show') : el.classList.remove("show"));
document.body.classList.add('bgcolor');
}
document.addEventListener('click', (e) => {
// cases where we want to close the dropdown
if (e.target.closest(".dropdown") === null) {
document.querySelectorAll('.dropdown-content').forEach(el => el.classList.remove("show"));
document.body.classList.remove('bgcolor');
}
});
*{margin:0;padding:0;}
.dropdown-content{
position: fixed;
width: 30%;
height:100%;
background-color: rgb(255,0,0);
margin-left: 20%;
top:0;
display:none;
z-index:100;
}
.dropbtn{width:20%}
.show{display:block;}
.bgcolor{
background-color:rgba(0,0,0,0.4);
}
<div class="dropdown">
<button class="dropbtn" onclick="toggleDropDown('openContent')">open</button>
<div class="dropdown-content" id="openContent">Hello, Div</div>
</div>
<h1>Hello World, Heading 1</h1>