What is the best way to use JavaScript to create an addEventListener that toggles a hamburger menu back and forth

Hi there! I'm currently in the final stages of polishing up my website before launching it online. However, I'm stuck on how to add an eventListener that will close the navbar hamburger menu without requiring manual scrolling back up to the top of the landing page. Here's what I've got so far.

//Function to select an element
const selectElement = function (element) {
    return document.querySelector(element);
};

let menuToggler = selectElement('.menu-toggle');
let body = selectElement('body');

menuToggler.addEventListener('click', function () {
    body.classList.toggle('open');
});

// Implementing a parallax scrolling effect
window.addEventListener('scroll', function () {
    const parallax = document.querySelector('.parallax');
    let scrollPosition = window.pageYOffset;
  
    parallax.style.transform = 'translateY(' + scrollPosition * -.10 + 'px)';
  });

For more context, here's a screenshot of the HTML document with the nav tag. I would greatly appreciate a detailed explanation of the JavaScript code as I am still relatively new to it. : ) Thank you! https://i.sstatic.net/4XI2l.png

I've also included a link to a video showcasing how the hamburger menu functions

Answer №1

If you want to close the navbar when clicking on a nav-link, you can achieve this with the following code:

const menuToggler = document.querySelector('.menu-toggle');
const body = document.body;
const navItems = document.querySelectorAll(".nav-item");

Array.from(navItems).map(el => {
  el.addEventListener('click', function () {
      body.classList.remove('open');
  });
});

menuToggler.addEventListener('click', function () {
    body.classList.toggle('open');
});

// Implementing a parallax scrolling effect
window.addEventListener('scroll', function () {
    const parallax = document.querySelector('.parallax');
    let scrollPosition = window.pageYOffset;

    parallax.style.transform = 'translateY(' + scrollPosition * -.10 + 'px)';
});

Answer №2

To implement an event listener on the entire document, you need to check if the clicked element is either the menu button, the navigation element (nav), or a child of the navigation element. If it does not match any of these conditions, then remove the specified class.

document.addEventListener('click',(e)=>{
    // Identify the clicked element
    let target = e.target;

    // Select the navigation element
    let nav = document.querySelector('nav');

    // Check if it's not the menu button, nav, or a child of nav
    if(target != menuToggler && target != nav && target.closest('nav') != nav){
        body.classList.remove('open');
    }
});

You can also utilize a key event such as pressing the ESC key to trigger the removal of the class.

document.addEventListener('keydown',(e)=>{
    if(e.key=="Escape"){
        body.classList.remove('open');
    }
});

If you wish to close the menu after clicking a link within the navigation section, include the remove code in your existing link listeners or incorporate a new one for the links. Alternatively, you can apply a delegated listener on the nav element and remove it from there.

document.querySelector('nav').addEventListener('click',(e)=>{
   if(e.target.classList.contains('nav-link')){
       body.classList.remove('open');
   }
});

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

The animation in ThreeJs encounters context issues within Angular 2

I am trying to incorporate ThreeJs into my Angular 2 project. I have successfully rendered a scene with a simple cube, but I ran into an issue when using the animate() function. Here is the code snippet: import { OnInit, Component } from '@angular/co ...

Utilizing JavaScript or PHP to assign a uniform class to dynamically generated elements

Hello! In my online shop, each category has a page with all subcategories and a table of products. I want each product row in the table to have the same color as its corresponding sorting button for the subcategory. This must be done dynamically as I hav ...

There was an error in reading the property 'RNFSFileTypeRegular' of null, with the JavaScript engine reporting as hermes

Below are the dependencies listed in my package.json file: "dependencies": { "@expo/vector-icons": "^14.0.2", "@react-navigation/native": "^6.0.2", "expo": "~51.0.23", & ...

Is there a way to use a single function to fill and calculate multiple input fields with PHP, Javascript, and

I've encountered an issue while trying to populate a form using Javascript/ajax/php. The problem is that my function only fills in one of the required forms and then stops, even though I have received the second response from the server. Here's ...

Utilizing React Hook Form for Interactive Slider and User Input Controls

Whenever I move the Slider, I want to retrieve the same value as when I enter a new value in the Input field. However, the current setup is not functioning correctly. <StyledSlider {register(NAME ...

Modifying the theme of the Angular UI-Bootstrap datepicker

I am currently facing an issue with my angular datepicker, which is appearing oversized and covering almost 30% of the screen. Additionally, there are large gaps between the dates in the calendar view. After some investigation, I believe this problem may ...

Nested tables in CSS

Creating a Gridview with two nested Gridviews in separate cells may result in some CSS inheritance issues. Each row of the table contains these nested Gridviews, but trying to isolate their style using CssClass doesn't always work effectively. Is the ...

Most efficient method for structuring back-end Node processes and integrating them with front-end Vue/Nuxt applications

Currently, I have a few small node applications performing simple tasks such as checking information and updating my database using CRON jobs. As I begin working on my Nuxt app, I realize that I will need to incorporate some of the functionality from these ...

What steps can I take to address the div issue in my React application?

After implementing Browser Router, I am encountering whitespace on the left and right side of the navbar. How can I resolve this issue? Below is the code snippet: <div className="container my-3"> <BrowserRouter> ...

Jeditable Failing to Retrieve "id" Value

I am facing an issue with retrieving the correct "id" from my Jeditable function. My code looks like this: <li id="249" rel="4"> <span title="Double-click to edit...">EDIT THIS TEXT</span> <div class="tab"></div> </li ...

Guide to changing the size of an image window in CSS when the container's width falls below a specific threshold

I am struggling with a dilemma regarding an image that is 1920 pixels wide. My goal is to have it displayed centered and cropped in the browser window when its width exceeds 1024 pixels. In case the browser width is below 1024 pixels, I want the image to b ...

Using Regex to detect recurrent (similar) patterns in jQuery <input> tags

I need assistance with ensuring that users input article numbers in the correct format, like this: ABC_ABC123; AB__B2A4; ABF_323WET; ... Currently, I have a regex pattern that works for one article number: var mask1 = /^([A-Z]{2})([A-Z|_]{1})_([A-Z0-9]{ ...

Revolutionary newspaper design utilizing asp.net's C# web forms

Trying to create a dynamic newspaper layout using ASP.NET C# web form. Struggling to set the page layout size inside a slider and display specific news content on a new page when clicking on an area of the newspaper using Repeater or another suitable contr ...

Strange FontAwesome input placeholder issue

I'm trying to use an icon from FontAwesome in the placeholder of an input field. Here is my code snippet: <input type="password" name="password" placeholder="&#xf023; &nbsp; Password"> However, when I view it on the screen, it appear ...

Javascript regular expression fails to find a match

Is there a way to match all strings except for the ones containing '1AB'? I attempted it but it returned no matches. var text = "match1ABmatch match2ABmatch match3ABmatch"; var matches = text.match(/match(?!1AB)match/g); console.log(matches[0]+" ...

After running the command "npx/npm create-react-app hello" to create a react app, I received the following message

Whenever I try to execute this command for creating a React app: C:\WINDOWS\system32> npm i create-react-app -g hello I receive the following message in my cmd prompt: npm WARN deprecated <a href="/cdn-cgi/l/email-protection" class="__cf ...

Searching for a way to access the child window URL within the parent window on a React.JS platform?

I am working on a ReactJS code and I need to open another URL in my child component. twitterPopup = () => { var currentChild = false; if (currentChild) child.close(); child = window.open( "http://10.10.1.1:9090/api/v1/twitter/login" ...

Stop the Bootstrap accordion from collapsing when clicking on an internal anchor (href)

Is there a way to prevent the accordion from collapsing when opening a new page after clicking on a link? I have included the HTML code below, but I need assistance with the JavaScript to achieve this. I'm facing an issue where the accordion category ...

Enhance HTML Performance with Resource Preloading

Just a quick query I wanted to throw out there - would prefetching resources like js scripts and images actually slow down the page load time? For instance, let's say I have a page with several links such as: <link rel="prefetch" href="http://exa ...

Implementing fetch within a custom hook to display a loader within a return function

customFetch hook: import React, { useState, useEffect } from 'react'; const customFetch = (url, options) => { const [response, setResponse] = useState(null); const [error, setError] = useState(null); useEffect(() => { (async () ...