Search code examples
jquerydrop-down-menucss-transitionstoggleclass

Using jquery to control css3 transitions to open and close nested menu dropdowns


I am using Jquery to control the css3 transition (margin) animation of a nested dropdown menu. I can get the nested menus to dropdown on click of the link that triggers the event in the main part of the menu, then if I click the same trigger again it closes the dropdown which it is supposed to do. But if I click all the dropdown triggers all the dropdowns menus are all visible at the same time.

What I am after is when I click another dropdown trigger in the same main menu, if one of the dropdowns is already open, the open one will close using css3 transition controled with Jquery as the new one opens. So only one dropdown can be open at a time.

I am new to jquery and I am aware that the jquery below is not the best way to do this. Any guidance in the right direction is much appreciated.

Jquery:

$(function() {  
    $("#drop1").click(function() {  
        $(".sub1").toggleClass("submenu");
    });  
});

$(function() {  
    $("#drop2").click(function() {  
        $(".sub2").toggleClass("submenu");
    });  
});

$(function() {  
    $("#drop3").click(function() {  
        $(".sub3").toggleClass("submenu");
    });  
});

CSS:

ul {width:100%; list-style: none; display:block;}

ul li {display:inline-block; width: 20%; height: 40px; float:left; background: #ccc; text-align:center;}

ul li a {display:block; width:100%; height: 40px; position:relative;}

.sub1, .sub2, .sub3 {width:300px; margin: -40px 0 0 0; position:absolute; z-index:-1;
transition: margin 0.2s ease; 
-moz-transition: margin 0.2s ease; 
-webkit-transition: margin 0.2s ease;
-o-transition: margin 0.2s ease;
-ms-transition: margin 0.2s ease;}

.submenu {margin:0; background: #666;}

.sub1 li, .sub2 li, .sub3 li {text-align:center; width: 33%;}

HTML:

<ul>
    <li>normal</li>
    <li><a id="drop1" href="#">drop</a>
        <ul class="sub1">
            <li>drop</li>
            <li>drop</li>
            <li>drop</li>
        </ul>
    </li>
    <li><a id="drop2" href="#">drop</a>
        <ul class="sub2">
            <li>drop</li>
            <li>drop</li>
            <li>drop</li>
        </ul>
    </li>
    <li>normal</li>
    <li><a id="drop3" href="#">drop</a>
        <ul class="sub3">
            <li>drop</li>
            <li>drop</li>
            <li>drop</li>
        </ul>
    </li>
</ul>

Solution

  • I would go for a simpler solution, I hope it helps you (I have tested it).

    You will need to change a bit of your code, to make the links that activate the dropdown all members of the same class, in this case drop. For example:

    <a id="drop1" href="#" class="drop">drop</a>

    You should do that for all the dropdown selectors (#drop1, #drop2, #drop3).

    Then use this function:

    $(function() {  
        $("a.drop").click(function() {  
        $('.submenu').not( $(this).next() ).toggleClass("submenu");
            $(this).next().toggleClass("submenu");
        });  
    });
    

    What this will do is:

    1. Check if there is a submenu already in place, and if this submenu is not the current that we are clicking. This toggles again (disable submenu) every element that is not which we are clicking (because that one will be toggled in the next line). That is made in the first line of the function.
    2. Then, it will toggle the class of the current clicked element.

    We need both lines, because the menu has a state where none of the elements is showing its submenu.

    The $(this).next() is used in this case because your submenu is the next element to the clicked one; in other words, its just after the that activates the click.