"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

tips for selecting various API requests based on the selected drop down menu choice

Hey there! I'm looking to enhance my login page by adding a feature that allows users to select from a dropdown menu with different options. Each option will be linked to a specific API, and based on the API response, the user's ability to log in ...

Tips for effectively wrapping Material UI v5 component to ensure the Grow component functions correctly

Being a newcomer to React, I want to apologize in advance for any silly mistakes or inaccuracies that may be present. I have successfully implemented the code for my Blog page: export default function Blog() { const [photos, setPhotos] = useState([]); ...

Executing two SQL queries simultaneously in NodeJS can be achieved by using a single statement

app.get("/total", function(req,res){ var q = "SELECT COUNT(*) AS new FROM voters_detail WHERE parties LIKE '%BJP%'"; connection.query(q, function(err, results){ if(err) throw err; var hello = results[0].new; res.send("BJP Was Voted By ...

Stream-Awesome #12: The Return of Duplexer in Nodesville

For days, I've been attempting different methods to solve this exercise. It's frustrating because no matter what I try, I keep encountering a "write after end" error. But here's the thing - I'm using the "end" event and not writing anyt ...

Homepage divided in two sections akin to the Tumblr landing page

Have you ever visited www.tumblr.com and noticed the '30 reasons...' link on the registration page that slides up and reveals a second page? I've been trying to figure out how they achieve this cool effect. Most tutorials show how to scroll ...

In JavaScript, creating a new array of objects by comparing two arrays of nested objects and selecting only the ones with different values

I've been struggling to make this work correctly. I have two arrays containing nested objects, arr1 and arr2. let arr1 =[{ id: 1, rideS: [ { id: 12, station: { id: 23, street: "A ...

Is there Polyfill Compatibility for Custom Elements in Angular 9?

When it comes to polyfilling support for custom elements created with Angular, there are various recommendations available. This demo demonstrates that adding the following polyfill in polyfills.ts works: import '@webcomponents/webcomponentsjs/custo ...

Attempting to adjust the width of a text animation loaded with jQuery using Textillate, but encountering difficulties

I found a captivating animation on this website: http://codepen.io/jschr/pen/GaJCi Currently, I am integrating it into my project. #content { position: relative; margin-left: auto; margin-right: auto; width: 1000px; height: 700px; } ...

Guide on using a pipe feature with varying arguments when the main function is called

I am delving into functional programming for the first time and have a query regarding using pipes. Imagine I have this particular function: const updateArray = R.curry((index, value, array) => Object.assign([], array, {[index]: v ...

Is it possible to execute an ajax function at regular intervals until a specific condition is fulfilled?

My application consists of two JSP pages. One is responsible for the UI, while the other processes the response. UICounter.jsp: <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Page</titl ...

Vue.js / Nginx / Node.js - Error 413: Payload Too Big

My frontend is built using Vue.js and is hosted on an nginx server in production. Here's a snippet of my nginx.conf configuration: server { listen 80; server_name localhost; root /usr/share ...

Spring Boot is having trouble identifying the JavaScript files

I've incorporated Spring Boot in my project and I'm working with a JSP file that looks like this: <%@ include file="common/header.jsp" %> <%@ include file="common/navigation.jsp" %> <div class="container"> ...

Passing a JavaScript variable to PHP resulted in the output being displayed as "Array"

After sending a JavaScript variable with the innerHTML "Basic" to PHP via Ajax and then sending an email with that variable, I received "Array" instead of "Basic". This situation has left me puzzled. HTML: <label class="plan-name">Plan name: <b ...

The alignment of the third column div is off and not displaying properly

I am having some trouble with aligning the divs on my page in a column layout. Despite setting the first two divs to float left, the third one does not align properly. I want the third div to be floated right and aligned with the first two. You can see an ...

Using jQuery to automatically select a specific radio button after the load() function is executed

I'm trying to dynamically load radio buttons into a div using the JQuery load() function. However, I'm facing an issue when it comes to checking a specific radio button by its value. The problem is that the code doesn't seem to be working w ...

Vue - Error Message from Eslint Regarding Absence of Variable in Setup Function

Interestingly, the Vue.js documentation strongly recommends using the <script setup> syntax of the Composition API. The issue with this recommendation is that the documentation lacks depth and it conflicts with other tools (like eslint). Here is an e ...

issue arising where the table's border is not displaying

I'm confused about why the border of the first tbody tr's td is not visible. https://i.stack.imgur.com/Fwlv7.png I can't see any reason why the border is not showing up. Here's what I've figured out: If the natural height of th ...

How to Disable a Button with JavaScript in a Vue.js Application Without Using jQuery

I'm currently in the process of transitioning old jQuery code to JavaScript for a Vue.js application. function DisableSubmit() { submitButton.prop('disabled', true); submitButton.attr('data-enabled-value', submitButton.val ...

sliding to the right gets jammed

I am encountering a peculiar issue with Multi-page slide functionality. Whenever I attempt to switch pages, the new page gets stuck on the left before sliding out into position. Feel free to test this problem using my JSFiddle This is the JQuery code that ...

Efficient code for varying layouts of disabled Angular Material buttons

I've been wondering if there's a simpler way to customize the appearance of a disabled button using Angular Material. Currently, I achieve this by utilizing an ng-container and ng-template. While this method gets the job done, the code is not ve ...