Creating Stylish Sliding Menu With JQuery

Today, we are going to create a very stylish sliding menu as shown in the picture on the left with the help of JQuery. Before we move on, please have a look at the demo of this menu.

In order to create this menu what is usually known as accordion, we will be adding HTML of course, CSS to style the menu and finally JQuery to create the kind of effect this menu has. Of course, once you create this menu, you can style it anyway you want; for example you can create background, active or hover images which can make this menu even more attractive or simply use colors instead. Ok, so let’s move on to creating this menu.

.

HTML

We will be using unordered lists for our menu. Here is how it looks like:

   <ul class="parent">
    	<li>
            <a href="#" class="slide">Title One</a>

            <ul class="child">
            	<li><a href="#">Link One</a></li>
                <li><a href="#">Link Two</a></li>
                <li><a href="#">Link Three</a></li>
                <li><a href="#">Link Four</a></li>
                <li><a href="#">Link Five</a></li>
            <!--<span class="hiddenSpellError" pre=""-->ul>

         </li>
    <!--<span class="hiddenSpellError" pre=""-->ul>
<!-- and more -->

As can be seen, there are two lists, the one with the class parent and other with that of child. The first list item of the parent list contains a link which is actually a heading that when clicked will show sub-links which are there in the child list. So the same markup structure goes for the rest of the headings and links.

The CSS

Here is the CSS for the menu:

a
{
	outline:none;
}

ul
{
	list-style:none;
}

ul.parent
{
	margin:0px;
}

ul.parent a
{
	display:block;
	width:200px;
	border-bottom:1px solid #336699;
	background:#3399FF;
	color:#FFFFFF;
	font-weight:bold;
	text-decoration:none;
	padding:7px;
}

ul.parent a:hover
{
	color:#000000;
	background:#66CC66
}

ul.child a
{
	background:#333333;
	color:#FFFFFF;
	border-bottom:1px solid #f6f6f6;
	font-weight:normal;
	margin-left:-40px;
	padding:7px;
	width:200px;
	display:block;
	line-height:10px;
}

ul.child a:hover
{
	color:#3333333;
	background:#CCCCCC
}

In some browsers, when you click on a link, an outline (sort of dotted border) is created around it, so we disable that behavior by setting:

a
{
	outline:none;
}

Then we remove the list style so that there are no bullets for ul lists and also remove any margins around it by setting value to 0:

ul
{
	list-style:none;
}

ul.parent
{
	margin:0px;
}

After that we set links’ display style to block so that we could apply a width to them and also set some other styles such as background:

ul.parent a
{
	display:block;
	width:200px;
	border-bottom:1px solid #336699;
	background:#3399FF;
	color:#FFFFFF;
	font-weight:bold;
	text-decoration:none;
	padding:7px;
}

Finally we set styles when mouse is over the links using :hover pseudo selector:

ul.parent a:hover
{
	color:#000000;
	background:#66CC66
}

JQuery

We use JQuery’s ready event which fires when DOM (document object model) becomes ready, the short version of this event is:

	$(function(){
	// code here
	});

When the page has loaded, we want to make sure that only the first heading and links are shown which can be done as follows:

	// hide all links except for the first
	$('ul.child:not(:first)').hide();

For each selected heading we set its color to #FF9900, so we want to change the color of the first heading so as to make it feel like selected by default when the page has loaded:

	$("a.slide:first").css("background-color","#FF9900");

Then we write the code for each heading’s click event:

	$('ul.parent a.slide').click(function(){
	});

What it means is that a link with class slide which is inside ul with class parent gets clicked, run the code specified. First, we set background color and mouse over and mouse out color for the current clicked heading and other headings:

	$('ul.parent a.slide').css("background-color","#3399FF");

	$('ul.parent a.slide').mouseout(function(){
		$(this).css("background-color","#3399FF");
	});

	$('ul.parent a.slide').mouseover(function(){
		$(this).css("background-color","#66CC66");
	});

	$(this).mouseout(function(){
		$(this).css("background-color","#FF9900");
	});

We now slide up all child elements:

	// slide all up
	$('ul.child').slideUp('slow');

Then we show the links of the current clicked heading:

	// show the links of current heading
	$(this).next().find('a').show();

$(this) refers to current clicked heading, that is $(‘ul.parent a.slide’, the next() method finds the next element in the hierarchy with respect to clicked element which is ul with class child, we find links inside that using find() method and finally show them. Finally, we slide down the ul with class child and prevent the default action of clicked link or heading.

Finally, we slide down the current heading:

  // slide down current heading
  $(this).next().slideDown('fast');

And we prevent default action of clicked heading which is actually
a link using:

// prevent default action
return false;

Here is the entire JQuery code:

	$(function(){
		// hide all links except for the first
		$('ul.child:not(:first)').hide();
		$("a.slide:first").css("background-color","#FF9900");

		$('ul.parent a.slide').click(function(){
			$('ul.parent a.slide').css("background-color","#3399FF");

			$('ul.parent a.slide').mouseout(function(){
				$(this).css("background-color","#3399FF");
			});

			$('ul.parent a.slide').mouseover(function(){
				$(this).css("background-color","#66CC66");
			});

			$(this).mouseout(function(){
				$(this).css("background-color","#FF9900");
			});

			// slide all up
			$('ul.child').slideUp('slow');

			// show the links of current heading
			$(this).next().find('a').show();

			// slide down current heading
			$(this).next().slideDown('fast');

			// prevent default action
			return false;
		});
	});

Download Code.

19 thoughts on “Creating Stylish Sliding Menu With JQuery

  1. Great menu,

    But how can i keep the current heading expanded when i’m on a childpage?
    i really need this option for a client and since i’m not that much into
    jquery i’m hoping to get an answer.

    Thanks 🙂

    • If you look at the code in that demo, the first line is this:

      $(‘ul.child:not(:first)’).hide();

      That starts by hiding all but the first menu. So you can change that to something like this:

      $(‘ul.child’).hide();//hide them all
      if (/*whatever logic here*/){
      $(‘ul.child:eq(0)’).show();//show first menu
      } else if (/*another decision*/){
      $(‘ul.child:eq(1)’).show();//show second menu
      }
      //etc

      • Thanks Sarfraz,

        This option works fine.
        There’s only one slight problem as the page i made is a WordPress.
        So the otions for example $(‘ul.child:eq(1)’).show();//show second menu
        would affect the 2nd heading too. So apllying it to all would make the whole menu
        collapse.

      • Hi Sarfraz,

        Great script. I was just wondering how i can apply a selected state to the second level (sub-nav items) in the same fashion as the top level.

        Regards
        Brendan

        • Hi,

          You should be able to do that easily by creating a click handler for child links eg $(‘ul.child a’).click(function(){ // your code }).

          And then simply remove and add class using removeClass and addClass but it is assumed that you already create a class in the styles. I could probably also selected/style a specific child menu with server side language based on which page is currently open.

          • Hi Sarfraz,

            Many thanks for getting back to me. I have implemented as you suggested and everything pretty much works fine. I do have one issue though and that is that i need to reset all the sub-nav selected states when clicking a main nav item. At the moment the last selected sub-nav item selected state is preserved. You can find my existing code below:

            $(function(){

            // Hide all sub-navs
            $(‘ul.child’).hide();
            // Highlight first option
            $(“a.slide:first”).css(“background-position”,”0px -15px”);

            // Main nav functions
            $(‘ul.parent a.slide’).click(function(){

            $(‘ul.parent a.slide’).css(“background-position”,”0px 0px”);

            $(‘ul.parent a.slide’).hover(function(){
            $(this).css(“background-position”,”0px -15px”);
            });

            $(‘ul.parent a.slide’).mouseout(function(){
            $(this).css(“background-position”,”0px 0px”);
            });

            $(this).mouseout(function(){
            $(this).css(“background-position”,”0px -15px”);
            });

            $(this).css(“background-position”,”0px -15px”);

            $(‘ul.child’).slideUp(‘slow’);

            $(this).next().find(‘a’).show();

            $(this).next().slideDown(‘slow’);

            return false;

            });

            // Sub nav functions
            $(‘ul.child a’).click(function(){

            $(‘ul.child a’).css(“background-position”,”0px 0px”);

            $(‘ul.child a’).hover(function(){
            $(this).css(“background-position”,”0px -15px”);
            });

            $(‘ul.child a’).mouseout(function(){
            $(this).css(“background-position”,”0px 0px”);
            });

            $(this).mouseout(function(){
            $(this).css(“background-position”,”0px -15px”);
            });

            $(this).css(“background-position”,”0px -15px”);

            return false;

            });

            });

            I have been trying to implement it but the behavior i need is that when you click a top-level nav item all sub-nav items are reset. Well if possible i’d like to have it so that the first sub-nav item is selected when sliding out the accordion.

            Cheers
            Brendan

              • Hi Sarfraz. That’s great and thanks for taking the time to respond. It does bring me back to my query though as your example with colours has the same issues i wish to address in my version. Once you’ve selected a sub-nav item (indicated with a red background in the css) should you then click another main-nav item the previously selected sub-nav item stays selected if you re-open the same section. I’m looking for a way to reset all sub-nav selected states when you click a different main-nav item. Any guidance on this you could give would be much appreciated.

                Regards
                Brendan

  2. Hi,

    I like this…
    but i have an issue about hyperlink not working in menu items.
    I just put hyperlink in href attribute as like…
    Title One

    but child links working fine
    Thanks

  3. i have been messing around with a couple of these menus and yours seems to be the nicest one i have found. i do have a common problem with them all though. i am building a site where the sidebar menu (your menu) will be included using php include, and what i need it to do is keep the state of the current expanded menu through out the selected pages. i have tried

    document.getElementById(“”).className += ” expand”;

    but was wondering if there was a way to do this through php instead of javascript. any ideas would be much appreciated.

    • You can use the trigger function of jQuery to actually click and open the respect submenu something like this:

      $(‘ul.parent a.slide’).eq(1).trigger(‘click’);

      You need to adjust the value of eq method accordingly with respect to your url.

  4. Ahmad,
    Could you tell me How can i implement this Slide Menu to my Word Press Theme Sidebar?
    Codes are here, but i have no idea where to put it.

    Kindly,
    Wali

  5. Hi, How can I edit hte script so that you can ‘slide up’ all parent menus, so all that is shown is the 4 or 5 parents. I’d want to set this as default. Thanks in advance.

    R

  6. Pingback: jquery slide menu, collapse all menus by default | Jisku.com - Developers Network

  7. Hi Ahmad,

    Thank you for your tutorial. It is detailed well.

    But I have a question. Firstly I would like the menu closed on page load, which I figured out how to do with my very basic knowledge of jQuery alongside your detailed notes.
    I replaced:
    $(‘ul.child:not(:first)’).hide();
    with
    $(‘ul.child’).hide();

    But is there a way to keep the bit of the menu open that has the current link (refering to the active page)? And the link showing an active colour as well?

    I’d really appreciate any help.

    Thank you!

Leave a comment