Press anywhere outside the slide menu to close it using Javascript

Hey, I've looked around and can't find a solution to my issue. I have a javascript menu that currently requires you to click the X button to close it. I want to be able to simply click anywhere outside the menu to close it instead.

<head>
<style>
.sidenav {
       height: 100%;
       width: 0;
      position: fixed;
      z-index: 1;
      top: 0;
      left: 0;
      background-color: #111;
      overflow-x: hidden;
      transition: 0.5s;
      padding-top: 60px;
    }
    
    .sidenav a {
      padding: 8px 8px 8px 32px;
      text-decoration: none;
      font-size: 25px;
      color: #818181;
      display: block;
      transition: 0.3s;
    }
    
    .sidenav a:hover {
      color: #f1f1f1;
    }
    
    .sidenav .closebtn {
      position: absolute;
      top: 0;
      right: 25px;
      font-size: 36px;
      margin-left: 50px;
    }
    
    @media screen and (max-height: 450px) {
      .sidenav {padding-top: 15px;}
      .sidenav a {font-size: 18px;}
    }
    </style>
    </head>
    <body>
    
    <div id="mySidenav" class="sidenav">
      <a href="javascript:void(0)" class="closebtn" onclick="closeNav()">&times;</a>
      <a href="#">About</a>
      <a href="#">Services</a>
      <a href="#">Clients</a>
      <a href="#">Contact</a>
   </div>

   <h2>Animated Sidenav Example</h2>
   <p>Click on the element below to open the side navigation menu.</p>
   <span style="font-size:30px;cursor:pointer" onclick="openNav()">&#9776; open</span>

   <script>
   function openNav() {
     document.getElementById("mySidenav").style.width = "250px";
   }

   function closeNav() {
    document.getElementById("mySidenav").style.width = "0";
   }
   </script>

Answer №1

If you want to make opening a side navigation menu easier, consider implementing an overlay on the entire page and utilizing a specific class for the open menu instead of manually adjusting the width of the sidenav:

function toggleSideNav() {
  document.body.classList.toggle('sidenav-open');
}
.sidenav {
  height:100%;
  width:0;
  position:fixed;
  z-index:1;
  top:0;
  left:0;
  background-color:#111;
  overflow-x:hidden;
  transition:.5s;
  padding-top:60px
}
.sidenav a {
  padding:8px 8px 8px 32px;
  text-decoration:none;
  font-size:25px;
  color:#818181;
  display:block;
  transition:.3s
}
.sidenav a:hover {
  color:#f1f1f1
}
.sidenav .closebtn {
  position:absolute;
  top:0;
  right:25px;
  font-size:36px;
  margin-left:50px
}

@media screen and (max-height:450px) {
  .sidenav {
    padding-top:15px
  }
  .sidenav a {
    font-size:18px
  }
}

#sidenav-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 0;
  height: 100%;
  background: rgba(0, 0, 0, .1);
  cursor: pointer;
  z-index: 1;
}

.sidenav-open .sidenav {
  width: 250px;
}

.sidenav-open #sidenav-overlay {
  width: 100%;
}
<div id="sidenav-overlay" onclick="toggleSideNav()"></div>
<div id="mySidenav" class="sidenav">
  <a href="#" class="closebtn" onclick="toggleSideNav()">&times;</a>
  <a href="#">About</a>
  <a href="#">Services</a>
  <a href="#">Clients</a>
  <a href="#">Contact</a>
</div>

<h2>Animated Sidenav Example</h2>
<p>Click on the element below to open the side navigation menu.</p>
<span style="font-size:30px;cursor:pointer" onclick="toggleSideNav()">&#9776; open</span>

Answer №2

Create a click event listener on the document and, within the listener, verify if the actual click originated from something other than the menu.

<head>
<style>
.sidenav {
       height: 100%;
       width: 0;
      position: fixed;
      z-index: 1;
      top: 0;
      left: 0;
      background-color: #111;
      overflow-x: hidden;
      transition: 0.5s;
      padding-top: 60px;
    }
    
    .sidenav a {
      padding: 8px 8px 8px 32px;
      text-decoration: none;
      font-size: 25px;
      color: #818181;
      display: block;
      transition: 0.3s;
    }
    
    .sidenav a:hover {
      color: #f1f1f1;
    }
    
    .sidenav .closebtn {
      position: absolute;
      top: 0;
      right: 25px;
      font-size: 36px;
      margin-left: 50px;
    }
    
    @media screen and (max-height: 450px) {
      .sidenav {padding-top: 15px;}
      .sidenav a {font-size: 18px;}
    }
    </style>
    </head>
    <body>
    
    <div id="mySidenav" class="sidenav">
      <a href="#" class="closebtn" onclick="closeNav()">&times;</a>
      <a href="#">About</a>
      <a href="#">Services</a>
      <a href="#">Clients</a>
      <a href="#">Contact</a>
    </div>
    
    <h2>Animated Sidenav Example</h2>
    <p>Click on the element below to open the side navigation menu.</p>
    <span id="open" style="font-size:30px;cursor:pointer" onclick="openNav()">&#9776; open</span>
    
    <script>
    function openNav() {
      document.getElementById("mySidenav").style.width = "250px";
    }
    
    function closeNav() {
      document.getElementById("mySidenav").style.width = "0";
    }
    
    let sidebar = document.getElementById("mySidenav");
    let open = document.getElementById("open");
    document.addEventListener("click", function(event){
      // If the event didn't originate from the open button or the sidebar, close it
      if(event.target !== sidebar && event.target !== open){
        closeNav();
      }
    });
    </script>

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

Retrieving a value attribute from the isolated controller of a directive

I have a directive that reads and writes attributes, but I'm having trouble getting it to work as expected. The issue seems to be with the controller inside main-directive.js, which is empty, while the actual action is happening in the isolated direct ...

the pause in execution before my function redirects to a different route

Currently, I am developing a page using nodeJs with express which is supposed to display a table. However, I encountered an issue with my variable "allMusique" that contains the data for my page. When trying to access it initially, there seems to be an err ...

Retrieve the desired element from an array when a button is clicked

When I click on the button, I need to update an object in an array. However, I am facing difficulties selecting the object that was clicked. For better readability, here is the link to my GitHub repository: https://github.com/Azciop/BernamontSteven_P7_V2 ...

Using javascript, retrieve the JSON values for each level

I need help using a recursive function in JavaScript to retrieve the last key value pair from a simple JSON object. Here is an example JSON object: { 'a': { 'b': { 'c': 12, 'd': 'Hello World& ...

Is it possible to include multiple URLs in a single cURL request to retrieve product information?

I am trying to retrieve products from the "generic/products" URL and the "generic/all_products" URL using a single cURL request. Here is my code: <?php $ch = curl_init(); $request_url = "HTTP://www.yourdomain.com/net/WebService.aspx?"; $request_u ...

Halt the CSS transition on the preceding element

I tried to pause a CSS transition and came across a question with a solution that seems similar: Is there a way to pause CSS transition mid-way? However, I couldn't make it work for my code. I suspect the issue lies with the before element. What cou ...

Issue: Configuration Error - CKEditor5 cannot be loaded for extension in Vuejs

Hey everyone, I'm currently facing an issue. I'm trying to customize a build and everything works fine in the cloned ckeditor along with the sample.html file. However, when attempting to implement the customized build in Vue 2, I encounter an err ...

I am facing difficulties in installing the necessary node modules for my Angular project

After attempting to run npm install, an error message is displayed towards the end: error syscall unlink 22396 error The operation was rejected by your operating system. 22396 error It's possible that the file was already in use (by a text editor or ...

Styling a Pie or Doughnut Chart with CSS

I am working on creating a doughnut chart with rounded segments using Recharts, and I want it to end up looking similar to this: Although I have come close to achieving the desired result, I am encountering some issues: Firstly, the first segment is over ...

Display each new array element on a separate line

let team = [['Sara', 'John', 'Kate']] let newTeam = team.map(function(r) { return r; }) outputs [ [ 'Sara', 'John', 'Kate' ] ] Is there a way to modify it so that each value is r ...

Vue chart not displaying data until the window is resized

I've encountered an issue with my apexchart where the data is not displayed when the page loads. It only appears when I zoom in/out or resize the window, which seems odd to me. I came across a similar problem on the apexcharts github, but it doesn&apo ...

Learn how to update image and text styles using Ajax in Ruby on Rails with the like button feature

I'm working on implementing a Like button in Rails using Ajax, similar to this example: Like button Ajax in Ruby on Rails The example above works perfectly, but I'm interested in incorporating images and iconic text (such as fontawesome) instead ...

Executing various count() queries on a MongoDB using mongoose

Hey there, I consider myself a MongoNoob and I know this question has probably been asked before in various ways, but I haven't found a specific solution yet. Let's imagine I have two Moongoose Models set up like this: var pollSchema = mongoose. ...

Creating a fantastic Image Gallery in JavaScript

As I work on creating a basic gallery page with html and css, everything seemed to be running smoothly. However, upon testing it in Google Chrome and IE, the onmouseover function is not responding as expected. The idea is for a larger image to display in t ...

Is it possible to modify a JavaScript array variable without having to refresh the page by utilizing Ajax?

Is it possible to update a JavaScript array variable without having to reload or refresh the page? I have an existing list of data in an array, and I retrieve additional data using PHP and Ajax. Now I want to add the new data obtained from PHP Ajax to th ...

What is the process for utilizing a custom plugin within the <script setup> section of Vue 3?

//CustomPlugin.js const generateRandomValue = (min, max) => { min = Math.ceil(min); max = Math.floor(max); const random = Math.floor(Math.random() * (max - min + 1)) + min; console.log(random); }; export default { install(Vue) { Vue.conf ...

The functionality of passing POST variables to the model seems to be malfunctioning in PHP CodeIgniter when attempting to use the

I attempted the code snippet below: function doAjax() { var sList = ""; $('input[type=checkbox]').each(function () { var sThisVal = (this.checked ? "1" : "0"); ...

Authentication for REST API using JavaScript in the web browser

Currently, I am experimenting with creating a stateless, REST-based API that I intend to use from multiple sources, one of which will be a single-page Javascript web application. The goal is to have a unified API for different clients, even those developed ...

Obtain the content of a clicked item on the following page using NextJs

I am currently working on a nextjs app that displays a list of 10 movies on the homepage, each with a Button / Link that leads to a specific page for that movie where all its content is shown. Initially, I tried adding the movie id to the Link like this: ...

Load suggestions from Material UI AutoComplete dynamically based on user input

I am facing a challenge with an Autocomplete component that needs to handle a large data list, up to 6000 elements, and display suggestions based on user input. Due to the sheer number of options, when a user types on a slower computer, there is a noticeab ...