"Learn the steps to toggle a sub menu using an onclick event and how to hide it using another

I created a sidebar navigation that displays submenus on mouseover, but I want them to open on click and close when clicking on the same tab. Please take a look at my code on this CodePen link. Thank you.

<nav class="navigation">
  <ul class="mainmenu">
    <li><a href="">Home</a></li>
    <li><a href="">About</a></li>
    <li><a href="">Products</a>
      <ul class="submenu">
        <li><a href="">Tops</a></li>
        <li><a href="">Bottoms</a></li>
        <li><a href="">Footwear</a></li>
      </ul>
    </li>
      <li><a href="">Contact us</a></li>
  </ul>
</nav>

Link to the CodePen demo

Thank you in advance for your help.

Answer №1

Utilize a hidden checkbox along with the general sibling combinator (~) to toggle the sub menu open and closed upon clicking, all without the need for javascript:

html, body {
    font-family: Arial, Helvetica, sans-serif;
}
.navigation {
  width: 300px;
}
.mainmenu, .submenu {
  list-style: none;
  padding: 0;
  margin: 0;
}
.mainmenu a, .mainmenu label {
  display: block;
  background-color: #CCC;
  text-decoration: none;
  padding: 10px;
  color: #000;
}
.mainmenu a:hover, .mainmenu label:hover {
    background-color: #C5C5C5;
}

/* hide the input */
.mainmenu input {
  display: none;
}
/* if a sibling checkbox is check show the menu */
.mainmenu input:checked ~ .submenu {
  display: block;
  max-height: 200px;
}
.submenu a, .submenu label {
  background-color: #999;
}
.submenu a:hover {
  background-color: #666;
}
.submenu {
  overflow: hidden;
  max-height: 0;
  transition: all 0.5s ease-out;
}
<nav class="navigation">
  <ul class="mainmenu">
    <li><a href="">Home</a></li>
    <li><a href="">About</a></li>
    <li><input type="checkbox" id="products">
      <label for="products">Products</label>
      <ul class="submenu">
        <li><a href="">Tops</a></li>
        <li><a href="">Bottoms</a></li>
        <li><a href="">Footwear</a></li>
      </ul>
    </li>
    <li><a href="">Contact us</a></li>
  </ul>
</nav>

Answer №2

Hopefully, this solution is helpful for you. I have incorporated some jQuery code and utilized Ids for the target submenu. This script can be repeated for other submenu items by simply modifying the Ids accordingly. Additionally, I have provided an example specifically for the "About" tab, wherein clicking on another tab will automatically close any open submenu within that tab.

$('.dropdown').click(function () {
  var target_id = $(this).attr('data-toggle');
  $('.dropdown-list').not(target_id).slideUp();
  $(target_id).slideToggle();
  $('.dropdown-list').not(target_id).parents('li, .icon-tab').removeClass('active');
  $('.dropdown').not(this).parents('.icon-tab').removeClass('active');
  $(this).parents('li, .icon-tab').toggleClass('active');
});
html, body {
    font-family: Arial, Helvetica, sans-serif;
}

/* define a fixed width for the entire menu */
.navigation {
  width: 300px;
}

/* reset our lists to remove bullet points and padding */
.mainmenu, .submenu {
  list-style: none;
  padding: 0;
  margin: 0;
}

/* make ALL links (main and submenu) have padding and background color */
.mainmenu a {
  display: block;
  background-color: #CCC;
  text-decoration: none;
  padding: 10px;
  color: #000;
}

/* add hover behavior */
.mainmenu a:hover {
    background-color: #C5C5C5;
}


/* when hovering over a .mainmenu item,
  display the submenu inside it.
  we're changing the submenu's max-height from 0 to 200px;
*/

/*
  we now overwrite the background-color for .submenu links only.
  CSS reads down the page, so code at the bottom will overwrite the code at the top.
*/

.submenu a {
  background-color: #999;
}

/* hover behavior for links inside .submenu */
.submenu a:hover {
  background-color: #666;
}

/* this is the initial state of all submenus.
  we set it to max-height: 0, and hide the overflowed content.
*/
.submenu {
 
 display:none;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav class="navigation">
  <ul class="mainmenu">
    <li><a href="">Home</a></li>
    <li><a class="dropdown" data-toggle="#about">About</a>
      <ul class="submenu dropdown-list" id="about">
        <li><a href="">Tops</a></li>
        <li><a href="">Bottoms</a></li>
        <li><a href="">Footwear</a></li>
      </ul>
    
    </li>
    <li><a class="dropdown" data-toggle="#products">Products</a>
      <ul class="submenu dropdown-list" id="products">
        <li><a href="">Tops</a></li>
        <li><a href="">Bottoms</a></li>
        <li><a href="">Footwear</a></li>
      </ul>
    </li>
    <li><a href="">Contact us</a></li>
  </ul>
</nav>

Answer №3

give this a shot with JavaScript

$(document).ready(function(){

        $('.dropdown').each(function() {
          var $dropdown = $(this);

          $(".dropdown-link", $dropdown).click(function(e) {
            e.preventDefault();
            $div = $(".submenu", $dropdown);
            $div.toggle();
            $(".submenu").not($div).hide();
            return false;
          });

        });

        $('html').click(function(){
          $(".submenu").hide();
        });

      });
html, body {
            font-family: Arial, Helvetica, sans-serif;
        }

        /* set a fixed width for the entire menu */
        .navigation {
          width: 300px;
        }

        /* remove bullet points and padding from lists */
        .mainmenu, .submenu {
          list-style: none;
          padding: 0;
          margin: 0;
        }

        /* style all links with padding and background color */
        .mainmenu a {
          display: block;
          background-color: #CCC;
          text-decoration: none;
          padding: 10px;
          color: #000;
        }

        /* add hover effect */
        .mainmenu a:hover {
            background-color: #C5C5C5;
        }


        /* show submenu when hovering over a .mainmenu item 
          by changing max-height of the submenu to 200px
        */

        /* overwrite background-color for .submenu links only */
        .submenu a {
          background-color: #999;
        }

        /* hover effect for links inside .submenu */
        .submenu a:hover {
          background-color: #666;
        }

        /* initial state of submenus - max-height: 0 and hidden overflowed content */
        .submenu {
          overflow: hidden;
          display: none;
          -webkit-transition: all 0.5s ease-out;
        }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav class="navigation">
      <ul class="mainmenu">
        <li><a href="">Home</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-link">About</a>
          <ul class="submenu">
            <li><a href="">Tops</a></li>
            <li><a href="">Bottoms</a></li>
            <li><a href="">Footwear</a></li>
          </ul>
        </li>
        <li class="dropdown">
          <a href="#" class="dropdown-link">Products</a>
          <ul class="submenu">
            <li><a href="">Tops</a></li>
            <li><a href="">Bottoms</a></li>
            <li><a href="">Footwear</a></li>
          </ul>
        </li>
        <li class="dropdown">
          <a href="#" class="dropdown-link">Other dropdown</a>
          <ul class="submenu">
            <li><a href="">Tops</a></li>
            <li><a href="">Bottoms</a></li>
            <li><a href="">Footwear</a></li>
          </ul>
        </li>
        <li><a href="">Contact us</a></li>
      </ul>
    </nav>

Answer №4

This code snippet demonstrates the use of pure JavaScript to create a dynamic CSS animation effect.

Custom CSS Styles

.subrollin{
  overflow: hidden;
  max-height: 0;
  -webkit-transition: all 0.5s ease-in;
}
.subrollout{
  overflow: block;
  max-height: 200px;
  -webkit-transition: all 0.5s ease-out;
}

JavaScript Functionality

var element = document.getElementsByClassName('parentmenu')[0];
element.addEventListener("click", function(e) {
var sub = document.getElementsByClassName('submenu')[0];
  if(sub.classList.contains('subrollout')){
      sub.classList.add("subrollin");    
      sub.classList.remove("subrollout");
  } else {
      sub.classList.add("subrollout");
      sub.classList.remove("subrollin");
  }
}, false);

To view this code in action, check out the CodePen example at: https://codepen.io/anon/pen/gzpaer

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

Using AngularJS to handle click events and blur events

I am attempting to dynamically change the class based on user interaction in my code. The class should switch between "large" and "active" depending on whether the input field is filled or not. Please see the modified script below. <div class="snippe ...

Sliding an image from the left side to the right, and then repeating the movement from left to right

I am currently working on a CSS effect for some images. My goal is to have an image appear from the left side, move towards the right side, then reappear from the left and repeat this cycle. I managed to achieve this using the code below: @keyframes sli ...

"Learn how to easily format specific characters in JavaScript using the text plugin to create bold text strings with a unique

I would like to transform this text into something like "|| something 1 || something 2 || more || last one ||" and then make all of that string bold by adding "|" around it then it would look like this "|| something 1 || something 2 || more || last one | ...

Having trouble with the jQuery select2 AJAX functionality?

I've been experimenting with the jQuery select2 plugin and attempting to integrate AJAX with my external data, but unfortunately it's not working as expected. I'm curious if anyone can help me identify what mistake I might be making or if th ...

What is the best way to insert an iframe using getElementById?

I am looking to make some changes in the JavaScript code below by removing the image logo.png lines and replacing them with iframe code. currentRoomId = document.getElementById('roomID').value; if ( document.getElementById('room_' + c ...

Transfer of part of a JSON object

My current setup involves an API in PHP that sends JSON data to a Javascript webpage for processing. However, when dealing with large datasets, it can strain both the user's internet connection and computer capabilities. To address this issue, I want ...

Only include unique objects in the array based on a common property

I am currently working with the following array: [ {name: "Mike", code: "ABC123"}, {name: "Sarah", code: "DEF456"}, {name: "John", code: "GHI789"}, {name: "Jane", code: "JKL01 ...

Is there a better approach to verifying an error code in a `Response` body without relying on `clone()` in a Cloudflare proxy worker?

I am currently implementing a similar process in a Cloudflare worker const response = await fetch(...); const json = await response.clone().json<any>(); if (json.errorCode) { console.log(json.errorCode, json.message); return new Response('An ...

Updating the DOM using jQuery after receiving an AJAX response

I'm grappling with the most effective way to modify the DOM after receiving an AJAX response. I prefer to showcase the code rather than attempt to articulate my dilemma. // page contains several checkboxes $("input[type='checkbox']").live(& ...

Ways to position Drop-down menu flush against the left edge of the webpage?

I am facing a challenge in customizing my CSS3 Mega drop-down menu. I want the mega menu to start from the left side of the main page, beginning from the home button area and extending all the way to the end. Currently, it is appearing where the parent men ...

What is the best way to create hover effects on buttons in Vue.js 3?

I'm currently developing a calculator to practice my Vue.js 3 skills (I am new to vue). I've successfully implemented the basic features, but now I'm exploring how to incorporate hover animations on the buttons. Specifically, I want to diffe ...

Styling elements with CSS when the cursor hovers over them

I have a unique design challenge where I have stacked elements - an image, text, and an icon. My goal is to make only the icon animate when any of these elements are hovered over. <style> .hvr-forward { display: inline-block; vertical-align: mi ...

Is there a Node.js method that is similar to jQuery AJAX's .complete() function

In the process of creating a Node.js API to enroll a user in a different web application, I encountered an issue. As part of the registration flow, the API called by the Node app using request is being redirected with a status code of 301 to another API to ...

Node.js - Creating seamless integration between Sequelize model JS and controller TS

Having trouble making my User.js model recognized inside my UserController.ts with sequelize in TypeScript. Edit: Unable to change the file extensions for these files. In the await User.findAll() part, an error occurs when running on the server, stating ...

Expanding the use of tagged template literals for passing additional arguments

Currently, I am utilizing styled-components and creating components through their tagged template literal syntax like this: const Button = styled.button` background-color: papayawhip; border-radius: 3px; color: palevioletred; ` In a specific scenar ...

What steps can be taken to activate a class upon a click event?

I have successfully implemented a hover function to change the background color on my element, but now I need to add an additional functionality to make the class active on click event as well. I have been struggling to find a solution for this issue and ...

Unable to import CSV file

I'm currently in the process of developing a CSV editor that involves importing a CSV file and converting it into HTML tables. Below is the code I have been working on: <html> <head> <title></title> </head> <body& ...

When a node using express encounters :id, it is directed to a specific location

Currently, I am in the process of creating a small API collection to familiarize myself with nodejs using express. In my project, I have included the line app.use("/v1/phrases", phraseRouter); Within the router file, the code looks like this: co ...

Exploring the foundational element within a JSON structure

I'm trying to retrieve the album names of various artists from a JSON file located at this link. My current approach involves writing the following code: var json = JSON.parse(request.responseText); //parse the string as JSON var str = JSON.stringify ...

The value of Component.name is not consistent during the BUILD process in NextJS

I have multiple pages with different layouts. To switch between layouts, I am currently using the Component.name in _app.js. While this approach works during development, after building and starting the project with npm start, it seems like the Component.n ...