The navigation icon on my website refuses to close

Hey there, I'm having some trouble creating a side navigation menu. The issue I am facing is that the menu opens without any problem, but then I can't seem to figure out how to close it using a second "onclick()" function.

If you could take a look at my fiddle, I would really appreciate some guidance on how to add an onclick function that will close the navigation when clicking on the nav icon again.

function myFunction(x) {
  x.classList.toggle("change");
  document.getElementById("mySidenav").style.width = "220px";
  document.getElementById("Content").style.paddingLeft = "0px";
  document.body.style.opacity = "0.1";

}
/* The side navigation menu */

.sidenav {
  height: 100%;
  width: 0;
  /* 0 width - change this with JavaScript */
  position: fixed;
  z-index: 400;
  right: 0;
  background-color: #0F0F0F;
  overflow-x: hidden;
  padding-top: 90px;
  transition: 0.5s;
  -webkit-transition: 0.5s;
  -moz-transition: 0.5s;
  opacity: 0.8;
}
/* The navigation menu links */

.sidenav a {
  padding: 8px 8px 8px 10px;
  text-decoration: none;
  font-size: 18px;
  text-align: right;
  vertical-align: middle;
  justify-content: center;
  display: flex;
  line-height: 20px;
  color: #FFFFFF;
  transition: 0.3s;
}
/* When you mouse over the navigation links, change their color */

.sidenav a:hover,
.offcanvas a:focus {
  color: #00CB10;
  text-decoration: underline;
}
.menu-icon {
  display: inline-block;
  position: fixed;
  z-index: 500;
  cursor: pointer;
  margin-right: 15px;
  margin-top: 15px;
  margin-left: 96%;
}
.bar1,
.bar2,
.bar3 {
  width: 30px;
  height: 4px;
  background-color: #0F0F0F;
  border-radius: 10px;
  margin: 6px 0;
  transition: 0.4s;
}
/* Rotate first bar */

.change .bar1 {
  -webkit-transform: rotate(-45deg) translate(-9px, 5px);
  transform: rotate(-45deg) translate(-9px, 5px);
}
/* Fade out the second bar */

.change .bar2 {
  opacity: 0;
}
/* Rotate last bar */

.change .bar3 {
  -webkit-transform: rotate(45deg) translate(-8px, -6px);
  transform: rotate(45deg) translate(-8px, -6px);
}
<div id="Menu" class="menu-icon" onclick="myFunction(this)">
  <div class="bar1"></div>
  <div class="bar2"></div>
  <div class="bar3"></div>
</div>

<div id="mySidenav" class="sidenav">
  <!--Start Side Nav-->
  <a href="#">Our Story</a>
  <a href="#">Products</a>
  <a href="#">Contact Us</a>
  <a href="#">Login/Sign up</a>
</div>
<!---->

Answer №1

Instead of adjusting the width in JS, consider toggling an additional class when the menu is open.

Also, be cautious about changing the body opacity as it can affect the menu; only adjust the main content div. Alternatively, you can display an overlay div with fixed positioning (100% width and height, background, and opacity) to create a disabled content effect.

In my example, I have commented unnecessary JavaScript lines and added some CSS:

function myFunction(x) {
  x.classList.toggle("change");
  //document.getElementById("mySidenav").style.width = "220px";
  //document.getElementById("Content").style.paddingLeft = "0px";
  document.body.style.opacity = "0.1";

}
/* The side navigation menu */

.sidenav {
  height: 100%;
  width: 0;
  /* 0 width - change this with JavaScript */
  position: fixed;
  z-index: 400;
  right: 0;
  background-color: #0F0F0F;
  overflow-x: hidden;
  padding-top: 90px;
  transition: 0.5s;
  -webkit-transition: 0.5s;
  -moz-transition: 0.5s;
  opacity: 0.8;
}
/* The navigation menu links */

.sidenav a {
  padding: 8px 8px 8px 10px;
  text-decoration: none;
  font-size: 18px;
  text-align: right;
  vertical-align: middle;
  justify-content: center;
  display: flex;
  line-height: 20px;
  color: #FFFFFF;
  transition: 0.3s;
}
/* When you mouse over the navigation links, change their color */

.sidenav a:hover,
.offcanvas a:focus {
  color: #00CB10;
  text-decoration: underline;
}
.menu-icon {
  display: inline-block;
  position: fixed;
  z-index: 500;
  cursor: pointer;
  margin-right: 15px;
  margin-top: 15px;
  margin-left: 96%;
}
.bar1,
.bar2,
.bar3 {
  width: 30px;
  height: 4px;
  background-color: #0F0F0F;
  border-radius: 10px;
  margin: 6px 0;
  transition: 0.4s;
}
/* Rotate first bar */

.change .bar1 {
  -webkit-transform: rotate(-45deg) translate(-9px, 5px);
  transform: rotate(-45deg) translate(-9px, 5px);
}
/* Fade out the second bar */

.change .bar2 {
  opacity: 0;
}
/* Rotate last bar */

.change .bar3 {
  -webkit-transform: rotate(45deg) translate(-8px, -6px);
  transform: rotate(45deg) translate(-8px, -6px);
}
.change + .sidenav {
  width: 220px;
}
<div id="Menu" class="menu-icon" onclick="myFunction(this)">
  <div class="bar1"></div>
  <div class="bar2"></div>
  <div class="bar3"></div>
</div>

<div id="mySidenav" class="sidenav">
  <!--Start Side Nav-->
  <a href="#">Our Story</a>
  <a href="#">Products</a>
  <a href="#">Contact Us</a>
  <a href="#">Login/Sign up</a>
</div>
<!---->

Answer №2

A new class titled toggleStyle has been implemented with the property width:220px. Additionally, a comment has been added for the line

document.getElementById("mySidenav").style.width = "220px"

See demo on JSFiddle

Answer №3

When attempting to adjust the width in JavaScript, it is important to first check if the menu is open.

In this scenario, the solution provided above seems to be the most appropriate.

function myFunction(x) {
  x.classList.toggle("change");
  var width=document.getElementById("mySidenav").style.width;
  if(width!="220px" || width=="") 
  {
     document.getElementById("mySidenav").style.width="220px";
  }
  else
  {
     document.getElementById("mySidenav").style.width="0px";
  }
  document.getElementById("Content").style.paddingLeft = "0px";
  document.body.style.opacity = "0.1";

}
/* Custom styling for the side navigation menu */

.sidenav {
  height: 100%;
  width: 0;
  /* Width will be adjusted using JavaScript */
  position: fixed;
  z-index: 400;
  right: 0;
  background-color: #0F0F0F;
  overflow-x: hidden;
  padding-top: 90px;
  transition: 0.5s;
  -webkit-transition: 0.5s;
  -moz-transition: 0.5s;
  opacity: 0.8;
}
/* Styling for the navigation menu links */

.sidenav a {
  padding: 8px 8px 8px 10px;
  text-decoration: none;
  font-size: 18px;
  text-align: right;
  vertical-align: middle;
  justify-content: center;
  display: flex;
  line-height: 20px;
  color: #FFFFFF;
  transition: 0.3s;
}
/* Change link color on hover */

.sidenav a:hover,
.offcanvas a:focus {
  color: #00CB10;
  text-decoration: underline;
}
.menu-icon {
  display: inline-block;
  position: fixed;
  z-index: 500;
  cursor: pointer;
  margin-right: 15px;
  margin-top: 15px;
  margin-left: 96%;
}
.bar1,
.bar2,
.bar3 {
  width: 30px;
  height: 4px;
  background-color: #0F0F0F;
  border-radius: 10px;
  margin: 6px 0;
  transition: 0.4s;
}
/* Rotate first bar */

.change .bar1 {
  -webkit-transform: rotate(-45deg) translate(-9px, 5px);
  transform: rotate(-45deg) translate(-9px, 5px);
}
/* Fade out the second bar */

.change .bar2 {
  opacity: 0;
}
/* Rotate last bar */

.change .bar3 {
  -webkit-transform: rotate(45deg) translate(-8px, -6px);
  transform: rotate(45deg) translate(-8px, -6px);
}
<div id="Menu" class="menu-icon" onclick="myFunction(this)">
  <div class="bar1"></div>
  <div class="bar2"></div>
  <div class="bar3"></div>
</div>

<div id="mySidenav" class="sidenav">
  <!--Start Side Nav-->
  <a href="#">Our Story</a>
  <a href="#">Products</a>
  <a href="#">Contact Us</a>
  <a href="#">Login/Sign up</a>
</div>
<!---->

Answer №4

Your setup is missing a crucial element - #mySidenav should be able to toggle between states along with .menu-icon.

To address this, you must modify myFunction() so that it toggles the class

.change</code for both <code>.menu-icon
and #mySidenav.

function myFunction() {
var x = document.getElementsByClassName('menu-icon')[0]; 
var mySidenav = document.getElementById('mySidenav');

x.classList.toggle('change');
mySidenav.classList.toggle('change');
}

var menuIcon = document.getElementsByClassName('menu-icon')[0];
menuIcon.addEventListener('click',myFunction,false);
/* The side navigation menu */

.sidenav {
height: 100%;
width: 0;
/* 0 width - change this with JavaScript */
position: fixed;
z-index: 400;
right: 0;
background-color: #0F0F0F;
overflow-x: hidden;
padding-top: 90px;
transition: 0.5s;
-webkit-transition: 0.5s;
-moz-transition: 0.5s;
opacity: 0.8;
}
/* The navigation menu links */

// CSS styles continued...

#mySidenav.change {
width: 220px;
}

#Content.change {
padding-left: 0;
}

body.change {
opacity: 0.1;
}
<div id="Menu" class="menu-icon">
<div class="bar1"></div>
<div class="bar2"></div>
<div class="bar3"></div>
</div>

<div id="mySidenav" class="sidenav">
<!--Start Side Nav-->
<a href="#">Our Story</a>
<a href="#">Products</a>
<a href="#">Contact Us</a>
<a href="#">Login/Sign up</a>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Avoiding Backbone Routing Conflicts when Implementing CSS3 Targeting

I have implemented a CSS target to create some basic animation in my Backbone project. However, I am facing an issue where the method I am currently using adds a #banner to the URL, which Backbone tries to interpret as a route if users refresh the page aft ...

Is the content within the div longer than the actual div itself when the width is set to 100%?

When working with a div of fixed width that contains only an input text box, and the width of the input is set to 100%, you may notice that it extends slightly beyond the boundaries of the div. For demonstration purposes, consider the following code: HTM ...

tips for concealing a row in the mui data grid

I am working on a data grid using MUI and I have a specific requirement to hide certain rows based on a condition in one of the columns. The issue is that while there are props available for hiding columns, such as hide there doesn't seem to be an eq ...

Creating a Timeless Banner with the Magic of `background:url()`

I have a banner placed within a div tag that displays my banner image. I am trying to create a fading effect when transitioning to the next image, but I am struggling to achieve this. I attempted to use jQuery fadeIn(), however, it did not work as expected ...

Having trouble with my intricate-box and grid layout - the images are all overlapping!

Could you please take a look at the image below and tell me what I might be doing incorrectly? When the page initially loads, pictures appear like this. However, if I refresh the page, the issue is resolved. https://i.sstatic.net/hIyA4.jpg If I remove th ...

Having trouble with AngularJs and moment.js integration?

Looking to create a simple webpage using Angular Js for date calculations. Utilizing moment.js from http://momentjs.com/ Below is the current code: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> ...

What is the best way to pick out specific passages of text

I'm attempting to create an autocomplete feature where the data is displayed in a div below the text box as the user types. While this typically involves ajax, I've simplified the approach without using jQuery autocomplete. Once the text appears ...

Tips for positioning the text and icon within a tag nestled in a paragraph tag?

Need help aligning text and icons inside paragraph tags on a tag. Here is the HTML code I'm currently using: <div class="application-intro"> <p><a class="btn" href=""><i clas ...

Integrate ThreeJs models into an Angular JS application

I have a question that pertains to my webapp development. I am currently utilizing Angular Js (v1.5/1.6) and I would like to incorporate some minimalistic 3D animated models by integrating Three Js. Although I have attempted to configure certain aspects, ...

Retrieving checkbox list values using jQuery

I am working with a div that contains some checkboxes. I want to write code so that when a button is clicked, it will retrieve the names of all the checked checkboxes. Can you provide guidance on how to achieve this? <div id="MyDiv"> .... <td> ...

The buttons within the bootstrap navbar are not properly collapsing or resizing when the screen size is decreased, causing them to overlap and maintain their

As a newcomer to bootstrap, I recently created a navbar with several buttons. However, when I reduce the screen size to 1000 pixels, the button text gets overwritten and the navbar extends off the screen. I don't want the navbar to collapse at this si ...

What is causing my ajax request to malfunction?

I'm encountering an issue while trying to send a request using AJAX. The request is successful when I use the following webservice: https://jsonplaceholder.typicode.com/users However, when I attempt to make the same request with my own service, I fac ...

Sending an array of objects in JavaScript to a controller

I have a dynamic form that I'm trying to submit to my Controller. Instead of sending just a string or an array with data, I need to pass an array of objects using ajax request after building the Javascript Array. The challenge is that when I send only ...

Visualization of extensive datasets in JavaScript

I'm currently developing a dashboard in JS for displaying sales data plots to users. Can anyone recommend a JavaScript library that meets the following criteria: Capable of plotting a large number of points (ex: 100k or more) Interactive functional ...

How do I customize the appearance of console.log messages stored in a string variable?

Looking to enhance the appearance of my console log output in a JavaScript script by utilizing different styling options. Here's a sample scenario: s=`Title 1 \n This is some text that follows the first title`; s=`${s} \n Title 2 \n T ...

Struggling to forward POST Request using Express and EJS

I'm currently developing an application using Node.js, Express, and EJS. The goal is to have the app redirect users to a different page (for example, from localhost:3000/ to localhost:3000/about) upon clicking a button. Despite successfully receiving ...

Restrict the height of posts created in the summernote editor

My goal is to create a structured page application using summernote. When using summernote, a div with contenteditable=true is appended to the body to allow users to add content. However, I want to set a fixed height for this div so that users can only ent ...

Tips for including vertical lines within text boxes to distinguish elements

I've been working on a simple form using CSS and HTML, but I'm struggling to add vertical lines to separate my text from the radio buttons. Right now, I'm just using '|' to divide them, but it's not the most visually appealing ...

I'm having trouble getting Jquery's insertAfter() function to function properly

After creating a parent div and using jQuery's insertAfter() method to insert additional divs, an unexpected issue arises. The first record goes to the bottom, while subsequent records are inserted above it. Below is the function in question: functi ...

Monitor the change in FileReader().readyState using AngularJS

Below is the AngularJS code I have written to read a local file. var files = document.getElementById("file"); files.addEventListener("change", handleFile, false); function handleFile(event) { SpinnerService.upload(); // Display loading spinner ...