Burger menu animation activated by a single click anywhere on the page

After following a tutorial on creating an animated menu burger, I encountered a few bugs. The animation is working as intended, but it triggers no matter where I click on the page. Here is the code snippet:

    const toggleMenu = document.querySelector(
        '.menu-btn');
    let isOpen = false;
    document.addEventListener('click', () => {
        if (!isOpen) {
            toggleMenu.classList.add('open');
            isOpen = true;
        } else {
            toggleMenu.classList.remove('open');
            isOpen = false;
        }
    });
.grid-container {
     display: grid;
     grid-template-areas: "header menu";
     grid-template-columns: repeat(8, 1fr);
    }
    .
    .
    .
    
    <!doctype html>
    <html>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="menu_design.css">

    <head>
     <div class="grid-container">
      <div class="item header">
       <ul class="nav-test">
        <li><a href="#">Home</a></li>
        <li><a href="#">About Me</a></li>
        <li><a href="#">Music</a></li>
        <li><a href="#">Tours</a></li>
        <li><a href="#">Contact</a></li>
       </ul>
      </div>
      .
      .
      .
    </head>
    </html>
    

I opted for percentages in the attribute values to enable adjustment according to screen size.

Upon viewing it on my desktop, I noticed some choppiness in the animation. Any advice on how to address this issue would be greatly appreciated.

On a side note, I acknowledge the presence of an extra bullet point list. This pertains to a sliding menu that opens upon clicking the burger and is unrelated to the current issue.

Answer №1

You can replace the document.addEventListener with toggleMenu.addEventListener

    const toggleMenu = document.querySelector(
        '.menu-btn');
    let isOpen = false;
    toggleMenu.addEventListener('click', () => {
        if (!isOpen) {
            toggleMenu.classList.add('open');
            isOpen = true;
        } else {
            toggleMenu.classList.remove('open');
            isOpen = false;
        }
    });
.grid-container {
     display: grid;
     grid-template-areas: "header menu";
     grid-template-columns: repeat(8, 1fr);
    }

    .header {
     grid-area: header;
     grid-column: span 7;
     margin: 2px;
     background-color: black;
    }

    .menu {
     grid-area: menu;
     grid-column: span 1;
     display: flex;
     padding: 0;
     margin: 0;
     justify-content: center;
     align-items: center;
    }
    .menu-btn {
     display: flex;
     justify-content: center;
     align-items: center;
     width: 80%;
     height: 80%;
     transition: all .5s ease-in-out;
     //border: 2px solid #fff;
    }

    .btn-mid {
     position: relative;
     width: 25px;
     height: 3px;
     background: #fff;
     border-radius: 2px;
     transition: all .5s ease-in-out;
    }

    .btn-mid::before,
    .btn-mid::after {
     position: absolute; /*Necessary for 3 bars*/
     content:'';
     width: 25px;
     height: 3px;
     background: #fff;
     border-radius: 2px;
     transition: all .5s ease-in-out;
    }
    .btn-mid::before {
     transform: translateY(-300%);
    }

    .btn-mid::after {
     transform: translateY(300%);
    }

    .top-menu {
     transition: all .5s ease-in-out;
     position: absolute;
     bottom: 100%; /*So that we can't initially see*/
     width: 100%;
     height: 50vh;
     z-index: -1;
     background: #000;
    }

    .top-menu-box {
     display: flex;
     justify-content: center;
     align-items: center;
     text-align: center;
     width: 100%;
    }

    .top-menu-box ul {
     list-style: none;
     text-align: center;
    }

    .top-menu-box ul li:hover {
     border-bottom: 2px solid #fff;
     transition: 0.25s;
    }

    .top-menu-box ul li a {
     color: #fff;
    }

    /*BUTTON ANIMATION*/
    .menu-btn.open .btn-mid {
     transform: translateX(-175%);
     background: transparent;
    }

    .menu-btn.open .btn-mid::before {
     transform: rotate(45deg) translate(125%, -1050%);
    }

    .menu-btn.open .btn-mid::after {
     transform: rotate(-45deg) translate(125%, 1050%);
    }

    .menu-btn.open .top-menu {
     bottom: 50%;
    }

    .menu-btn.open .top-menu-box {
     width: 100%;
    }
    /*END*/

    .nav-test {
      display: flex;
      direction: row;
      overflow: hidden;
      justify-content: space-around;
      padding: 0; //By default, padding is set
      list-style-type: none;
    }

    .nav-test a {
     color: white;
    }

    .menu {
     display: flex;
     grid-area: menu;
     grid-column: span 1;
     margin: 2px;
     background-color: black;
    }
    <!doctype html>
    <html>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="menu_design.css">
 
    <head>
     <div class="grid-container">
      <div class="item header">
       <ul class="nav-test">
        <li><a href="#">Home</a></li>
        <li><a href="#">About Me</a></li>
        <li><a href="#">Music</a></li>
        <li><a href="#">Tours</a></li>
        <li><a href="#">Contact</a></li>
       </ul>
      </div>
      <div class="item menu">
       <div class="menu-btn">
        <div id="middle" class="btn-mid"></div>
       </div>
       <script src="response.js"></script>
      </div>
      <div class="top-menu">
       <div class="top-menu-box">
        <ul>
         <li><a href="#">Home</a></li>
         <li><a href="#">About Me</a></li>
         <li><a href="#">Music</a></li>
         <li><a href="#">Tours</a></li>
         <li><a href="#">Contact</a></li>
        </ul>
       </div>
      </div>
     </div>
     </div>
    </head>
   </html>
    

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

Guide to creating a simple multi-column index linking each item to a specific page reference

Here's an idea I have in mind: Alan 12 | Byron 104 Alfred 54 | Charles 33 Ann 28 | Cleopatra 7 Basil 133 | Corey 199 ...

Troubleshooting: How to Fix Missing Sum Display in HTML Input Fields

I am new to the world of website programming and I am currently working on creating a basic sum equation using two input fields from the client-side. <!DOCTYPE html> <html> <head> </head> ...

The CSS styles are functioning correctly in index.html, but they are not applying properly in the component.html

When the UI Element is clicked, it should add the class "open" to the list item (li), causing it to open in a collapsed state. However, this functionality does not seem to be working in the xxx.component.html file. Screenshot [] ...

What is the reason behind having the activator of strict mode as the string 'use strict'?

While many users may associate strict mode with the code 'use strict'; or "use strict";, the question arises as to why strict mode is not activated with an expression like use strict; instead. ...

Show schedule in an HTML chart

I'm currently working with a table that displays the current status of a request. An example of how the table looks in HTML is shown below: https://i.sstatic.net/daDHy.png The table itself is quite simple, but I am having trouble figuring out how to ...

Delete ObjectId from Array using Node and Mongoose

Currently, I am working on a website that features a comments section for campsites. This platform is similar to Yelp but focuses on reviewing campsites. Each campsite in the MongoDB collection has a field called "comments" which stores the IDs of all comm ...

Completing the remainder of the page with CSS styling

Currently, I have three Divs positioned absolutely on the page - leftDiv, middleDiv, and rightDiv. The middleDiv has a width of 900px, which is fine. However, I need the leftDiv and rightDiv to fill the remaining space on the left and right sides, regardle ...

Tips for displaying a title within the border of a div

We have a client who is asking for a unique feature on their new website - they want the title to appear within the border of a text area. We need help figuring out how to achieve this using CSS/HTML. Take a look at the effect we are trying to create: htt ...

Retrieving Multiple Arrays of Variables in PHP Output

I am struggling to retrieve the GET Variables from the URL of this particular page. Here is the URL: http://thisthat.com/category/?field_issue_month_value%5Bvalue%5D%5Byear%5D=2013&field_issue_month_value%5Bvalue%5D%5Bmonth%5D=10 I am attempting to ...

Expand the div width to the specified measurement horizontally

Is there a way to horizontally collapse a div (container) to a specific width that I can adjust, effectively hiding its content? The collapse effect should move towards the left. <div id="container"> <button type="button" id="myButton"> ...

the key of the global variable object is not displaying as being defined

Currently tackling some old legacy code that heavily relies on JQuery, and I'm stuck at a critical juncture. It seems like the process begins with initializing vm.products in newView = new DOMObj(). Then comes the data call, where a worker iterates t ...

Validating Data in Laravel with a Single Rule

I just started working with Laravel and our system has multiple forms on one page to enter a single bitcoin wallet in each input field. Currently, users can enter the same wallet information in all inputs, but this is not correct. Is there a way to only al ...

Using CSS styling to dictate how browsers display web content, specifically through setting font size measurements in EM

On different mobile devices and various browsers such as Internet Explorer and Mozilla, the font size in some divs does not appear consistent. Specifically, on a Samsung Galaxy S6. I am using EM units: I know it may not be ideal but I prefer this method a ...

Keep a collection of completed promises stored in the inventory

Good day, I'm facing a challenge in Parse Javascript where I am trying to save items after receiving them in a loop. However, outside the loop, the array of objects remains empty. .. define global ** var filesUpload = []** for (var key in files) { ...

Guide on uploading a form submission to a MYSQL database using NODE.JS

I need help regarding a specific issue I am facing. In my EJS file, I have a partial named "test" which includes a multistepper form. Additionally, I have a JavaScript file called "verificationtrade.js" added to the project. The multistepper form allows us ...

Guide on setting up a route in Next.js

Recently, I developed a simple feature that enables users to switch between languages on a webpage by adding the language code directly after the URL - i18n-next. Here's a snippet of how it functions: const [languages, ] = React.useState([{ langua ...

Strategies for persisting data in React using local storage to ensure information is retained after page refresh

I am attempting to store searched recipes data in local storage so that when the user refreshes, the data from the last searched recipe will still be available. I have tried saving the recipes data to local storage when a new search request is made and se ...

Is Grouping Together Installed Private Modules Possible?

Exploring a modular JavaScript approach in my upcoming project is a new concept for me. I would prefer explanations to be simple due to my limited experience. I have uploaded my private package on npm: @name/package-name The private package contains mul ...

Graph only displays data after button is clicked

I have been working on customizing this jsfiddle to display database data. Check it out here: http://jsfiddle.net/jlbriggs/7ntyzo6u/ Using JSON, I am fetching data from my database and editing chart1 to display the database data: var chart, chartOption ...

What is the best way to transfer data between my express middleware functions?

Hello, I am new to working with Javascript/Node/Express and currently trying to interact with the Facebook Graph API. Below is an Express middleware function that I have set up: My goal is to follow these steps: Acquire a user authentication token fro ...