Reputation: 83
I've just begun to learn JavaScript.
I wrote a simple dropdown menu, but when you initially load the page, two clicks on the "dropdown"- button (with onclick attribute) are required for the link list to be displayed.
After that, it works as intended - you only need to click one time on the button to display/hide the list.
But why do I have to click two times on the button after intially loading the site?
Here's my HTML/CSS:
#dropbtn {
background-color: #4CAF50;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
}
#dropdown {
position: relative ;
display: inline-block;
}
#dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
}
#dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
#dropdown-content a:hover {background-color: #f1f1f1}
/*#dropdown:hover #dropdown-content {
display: block;
}*/
#dropdown:hover #dropbtn {
background-color: #3e8e41;
}
<h2>Dropdown Menu</h2>
<p>Just a simple menu with link list</p>
<div id="dropdown">
<button id="dropbtn" onclick="myFunction()">Dropdown</button>
<div id="dropdown-content">
<a href="#">Link 1</a>
<a href="#">Link 2</a>
<a href="#">Link 3</a>
</div>
</div>
<script>
function myFunction() {
if (document.getElementById('dropdown-content').style.display == "none")
{document.getElementById('dropdown-content').style.display = "block";}
else {document.getElementById('dropdown-content').style.display = "none";}
}
</script>
Upvotes: 2
Views: 2748
Reputation: 33
Another way you can do it, which involves Dennis Spierenburg answer is to change
function myFunction() {
if (document.getElementById('dropdown-content').style.display == "none")
{document.getElementById('dropdown-content').style.display = "block";}
else {document.getElementById('dropdown-content').style.display = "none";}
}
to
function myFunction() {
const myElement = document.getElementById('dropdown-content');
const myElementDisplay = getComputedStyle(myElement);
if (myElementDisplay.display === "none") {
myElement.style.display = "block";
}
else {
myElement.style.display = "none";
}
}
Upvotes: 0
Reputation: 9
I was having the same issue, basically the first click activates the event handler in Javascript and the second click is the one that actually works.
To work your way around this call the event handler as soon as the page loads in your HTML file:
<body onload="myFunction()">
This will also make the first click work when using a phone.
Upvotes: 0
Reputation: 643
@sdleihssirhc tells in another post how to check if a element is being displayed or not. check out this post.
return element.currentStyle ? element.currentStyle.display :
getComputedStyle(element, null).display;
This will give you the value of a styled element.
Upvotes: 0
Reputation: 115212
In the initial case value of display
property would be undefined unless you are setting css property using inline style attribute, so toggle the if condition and code blocks.
function myFunction() {
// cache the element for later use, which is one of the best practice
var ele = document.getElementById('dropdown-content');
if (ele.style.display == "block") {
ele.style.display = "none";
} else {
ele.style.display = "block";
}
}
#dropbtn {
background-color: #4CAF50;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
}
#dropdown {
position: relative;
display: inline-block;
}
#dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 1;
}
#dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
#dropdown-content a:hover {
background-color: #f1f1f1
}
/*#dropdown:hover #dropdown-content {
display: block;
}*/
#dropdown:hover #dropbtn {
background-color: #3e8e41;
}
<h2>Dropdown Menu</h2>
<p>Just a simple menu with link list</p>
<div id="dropdown">
<button id="dropbtn" onclick="myFunction()">Dropdown</button>
<div id="dropdown-content">
<a href="#">Link 1</a>
<a href="#">Link 2</a>
<a href="#">Link 3</a>
</div>
</div>
<script>
function myFunction() {
// cache the element for later use
var ele = document.getElementById('dropdown-content');
if (ele.style.display == "block") {
ele.style.display = "none";
} else {
ele.style.display = "block";
}
}
</script>
Or set display
property using inline style attribute.
<div id="dropdown-content" style="display:none">
<a href="#">Link 1</a>
<a href="#">Link 2</a>
<a href="#">Link 3</a>
</div>
#dropbtn {
background-color: #4CAF50;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
}
#dropdown {
position: relative;
display: inline-block;
}
#dropdown-content {
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 1;
}
#dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
#dropdown-content a:hover {
background-color: #f1f1f1
}
/*#dropdown:hover #dropdown-content {
display: block;
}*/
#dropdown:hover #dropbtn {
background-color: #3e8e41;
}
<h2>Dropdown Menu</h2>
<p>Just a simple menu with link list</p>
<div id="dropdown">
<button id="dropbtn" onclick="myFunction()">Dropdown</button>
<div id="dropdown-content" style="display:none">
<a href="#">Link 1</a>
<a href="#">Link 2</a>
<a href="#">Link 3</a>
</div>
</div>
<script>
function myFunction() {
// cache the element for later use
var ele = document.getElementById('dropdown-content');
if (ele.style.display == "none") {
ele.style.display = "block";
} else {
ele.style.display = "none";
}
}
</script>
The HTMLElement.style property is used to get as well as set the inline style of an element. While getting, it returns a CSSStyleDeclaration object that contains a list of all styles properties for that element with values assigned for the attributes that are defined in the element's inline style attribute. See the CSS Properties Reference for a list of the CSS properties accessible via style. The style property has the same (and highest) priority in the CSS cascade as an inline style declaration set via the style attribute.
Upvotes: 2
Reputation: 723
Actually your dropdown-content has no style within it at the beginning, it has a css associated to it. Just declare the display: none on the declaration and it will work as expected.
#dropbtn {
background-color: #4CAF50;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
}
#dropdown {
position: relative ;
display: inline-block;
}
#dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
}
#dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
#dropdown-content a:hover {background-color: #f1f1f1}
/*#dropdown:hover #dropdown-content {
display: block;
}*/
#dropdown:hover #dropbtn {
background-color: #3e8e41;
}
<h2>Dropdown Menu</h2>
<p>Just a simple menu with link list</p>
<div id="dropdown">
<button id="dropbtn" onclick="myFunction()">Dropdown</button>
<div id="dropdown-content" style="display: none">
<a href="#">Link 1</a>
<a href="#">Link 2</a>
<a href="#">Link 3</a>
</div>
</div>
<script>
function myFunction() {
if (document.getElementById('dropdown-content').style.display == "none")
{document.getElementById('dropdown-content').style.display = "block";}
else {document.getElementById('dropdown-content').style.display = "none";}
}
</script>
Upvotes: 2
Reputation: 4181
The style property of the HTML element is not derived from the css styles applied to the element. So you're not accessing your #dropdown-content
when you access style.display
. Instead what you might do is have a css class that you add or removing depending on it's state.
Example adopted from your code:
#dropbtn {
background-color: #4CAF50;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
}
#dropdown {
position: relative;
display: inline-block;
}
.hide {
display: none;
}
#dropdown-content {
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 1;
}
#dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
#dropdown-content a:hover {
background-color: #f1f1f1
}
/*#dropdown:hover #dropdown-content {
display: block;
}*/
#dropdown:hover #dropbtn {
background-color: #3e8e41;
}
<h2>Dropdown Menu</h2>
<p>Just a simple menu with link list</p>
<div id="dropdown">
<button id="dropbtn" onclick="myFunction()">Dropdown</button>
<div id="dropdown-content" class="hide">
<a href="#">Link 1</a>
<a href="#">Link 2</a>
<a href="#">Link 3</a>
</div>
</div>
<script>
function myFunction() {
let element = document.getElementById('dropdown-content');
if (element.classList.contains('hide')) {
element.classList.remove('hide')
} else {
element.classList.add('hide')
}
}
</script>
Upvotes: 1
Reputation: 561
Just replace none
with block
and block
with none
in the function, that's what you need.
Upvotes: 0