Toggle button takes two clicks
I have made a toggle button to show some navlinks on mobile screens. However on the first page load it takes two clicks. After that point it toggle perfectly fine. How can I make it so it functions correctly first time?
Heres the script that contains the function.
script.js
function ToggleNavLinks() { /
var navLink = document.getElementsByClassName("nav-links")[0];
if (navLink.style.display === "none") {
navLink.style.display = "flex";
}
else {
navLink.style.display = "none";
}
}
Heres the layout file that contains the front-end element. I have tested if it was the external script reference and it definitely works.
layout.hbs
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{title}}</title>
<meta charset="utf-8"/> <!-- Charset -->
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<link rel='stylesheet' href='/stylesheets/style.css'/>
<script type="text/javascript" src="/javascripts/script.js"></script>
</head>
<body>
<header>
<nav class="navbar">
<img class="logo" alt="logo" src="images/logo-stock.png">
<a class="nav-toggle" onclick="ToggleNavLinks()" >
<span class="bar"></span>
<span class="bar"></span>
<span class="bar"></span>
</a>
<!-- Links used in the navbar -->
<div class="nav-links">
<ul>
<li>
<a href="#">Home</a>
</li>
<li>
<a href="#">Projects</a>
</li>
<li>
<a href="#">Contact</a>
</li>
</ul>
</div>
</nav>
</header>
<div>
{{{body}}}
</div>
</body>
</html>
Ill also include the stylesheet in case that has anything to do with it.
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300&display=swap');
:root {
font-size: 16px;
font-family: 'Roboto', sans-serif;
--text-primary: white;
--text-secondary: #4c6bc1;
--bg-primary: #101316;
--bg-secondary: #181a1d;
}
* {
box-sizing: border-box;
}
body {
background-color: var(--bg-primary);
margin: 0;
padding: 0;
}
body::-webkit-scrollbar {
width: 0.25rem;
}
body::-webkit-scrollbar-track {
background: #181a1d;
}
body::-webkit-scrollbar-thumb {
background: #4c6bc1;
}
.navbar {
justify-content: space-between;
position: relative;
background-color: var(--bg-secondary);
display: flex;
justify-content: space-between;
align-items: center;
}
.navbar img {
width: 250px;
height: 100px;
}
.logo{
max-width: 100%;
height: auto;
}
.navbar-links {
height: 100%;
}
.nav-links ul {
margin: 0;
padding: 0;
display: flex;
}
.nav-links li {
list-style: none;
}
.nav-links li a {
font-size: 1.5rem;
text-decoration: none;
color: white;
padding: 1rem;
display: block;
}
.nav-links li a:hover {
color: #4c6bc1;
}
.nav-toggle {
position: absolute;
top: 1.5rem;
right: 1rem;
display: none;
flex-direction: column;
justify-content: space-between;
height: 21px;
width: 30px;
}
.nav-toggle:hover {
cursor: pointer;
}
.nav-toggle .bar {
height: 3px;
width: 100%;
background-color: white;
border-radius: 10px;
}
@media (max-width: 800px) {
.nav-toggle {
display: flex;
}
.nav-links {
display: none;
width: 100%;
}
.navbar {
flex-direction: column;
align-items: flex-start;
}
.nav-links ul {
width: 100%;
flex-direction: column;
}
.nav-links li {
text-align: center;
}
.nav-links.active {
display: flex;
}
element.style.display === 'none'
is true when the element has an inline style
attribute, which includes display: none
. Note that this is true regardless of the actual computed style property of the element. You can check it in this example:
console.log(document.querySelector('.test').style.display);
.test {
display: block !important;
}
code {
background-color: #eee;
}
<div style="display: none;" class="test">I haz <code>style.display === 'none'</code>. You are looking at me. Stop staring, it's not nice.</div>
To check the computed property of the display
, use
window.getComputedStyle(element).display === 'none'
In conclusion, replace
if (navLink.style.display === "none") {
with
if (window.getComputedStyle(navLink).display === "none") {