Create an Accordion Menu for Mobile Site Jquery and CSS

1.7k Views Asked by At

I have recently started designing a mobile website using media queries and browsing a few websites to see what they've done it seems accordion navigation menus are the way to go, scaling up to a normal horizontal navigation bar. I have browsed and browsed the internet looking for an accordion walkthrough but I can not seem to find one that explains it well enough.

A good example is the one from microsoft on their website. Here is my code so far:

<!DOCTYPE html>

<html>

<head>
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
    
<style>
    body {
padding: 0;
margin: 0;
}

#topMenu {
height: 50px;
width: 100%;
background-color: #cde;
display: block;
}

nav {
width: 100%;
height: auto;
display: block;
margin: 0;
padding: 0;
}

nav a {
text-decoration: none;
padding-left: 40px;
}

nav ul {
list-style: none;
display: block;
margin: 0;
padding: 0;
background-color: #ccc;
} 

nav ul li {
display: block;
width: 100%;
padding: 20px 0px 20px 0px;
border-top: 2px solid #abc;
}

nav ul ul {
height: 0;
overflow: hidden;
padding-top: 0px;
}

nav ul ul li a {
padding-left: 100px;
}
</style>
</head>

<body>

 <div id="topMenu"></div>
 <nav>
  <ul>
   <li><a href="">Link</a></li>
   <li><a href="">Link</a>
    <ul>
     <li><a href="">Link 1</a></li>
     <li><a href="">Link 2</a></li>
     <li><a href="">Link 3</a></li>
     <li><a href="">Link 4</a></li>
     <li><a href="">Link 5</a></li>
     <li><a href="">Link 6</a></li>
     <li><a href="">Link 7</a></li>
    </ul>
   </li>
   <li><a href="">Link</a>
    <ul>
     <li><a href="">Link 1</a></li>
     <li><a href="">Link 2</a></li>
     <li><a href="">Link 3</a></li>
     <li><a href="">Link 4</a></li>
     <li><a href="">Link 5</a></li>
     <li><a href="">Link 6</a></li>
     <li><a href="">Link 7</a></li>
    </ul>
   </li>
   <li><a href="">Link</a>
    <ul>
     <li><a href="">Link 1</a></li>
     <li><a href="">Link 2</a></li>
    </ul>
   </li>
   <li><a href="">Link</a></li>
   <li><a href="">Link</a></li>
   <li><a href="">Link</a></li>
  </ul>
 </nav>

</html>

These navigation bars have submenus [nav ul ul] that slide out when nav ul li is clicked. I was hoping somebody could point me in the right direction as to how I go about making a slide down sub menu on click, or help me with the code.
I thought there may have been a basic one people could start using and edit to customise themselves.

Thanks for any help.

3

There are 3 best solutions below

2
On

Check this out

https://jsfiddle.net/nqamazgz/3/

Unfortunately CSS does not have any click events, instead you will need to use JavaScript and/or jQuery. I used jQuery

All i did was add a class hide-nav to your nav with display none. And a button to click of course.

And a bit of jQuery

$(document).ready(function() {
    $('#topMenu-btn').on('click', function() {
        $('nav').slideToggle();
    });
});
1
On

There is no need for Javascript - you may use a Checkbox instead. Check out: http://codepen.io/TimPietrusky/pen/CLIsl

If you still want to do it with Javascript go for something like this:

// asuming, that nav-items that should trigger slidedown will have "#" as href
// while actual nav-items will have URLs
$('nav li a[href="#"]').on('click', function (e) {
    // prevent Click from redirecting
    e.preventDefault();
    // get the next ul after the li a clicked
    if ($(this).hasClass('visible')) {
        $(this).next('ul').slideUp(200).removeClass("visible");
    } $(this).next('ul').slideDown(200).addClass("visible");
});

CSS animation for height form 0 to auto wont work. See: How can I transition height: 0; to height: auto; using CSS?

0
On

Try something like this:

http://jsfiddle.net/kb668aag/

You'll need to modify the code a bit.

    <div id="topMenu"></div>
    <nav>
        <ul>
            <li><a href="">Link</a></li>
            <li class="has_children"><a href="">Link</a>
                <ul class="sub-menu">
                    <li><a href="">Link 1</a></li>
                    <li><a href="">Link 2</a></li>
                    <li><a href="">Link 3</a></li>
                    <li><a href="">Link 4</a></li>
                    <li><a href="">Link 5</a></li>
                    <li><a href="">Link 6</a></li>
                    <li><a href="">Link 7</a></li>
                </ul>
            </li>
            <li class="has_children"><a href="">Link</a>
                <ul class="sub-menu">
                    <li><a href="">Link 1</a></li>
                    <li><a href="">Link 2</a></li>
                    <li><a href="">Link 3</a></li>
                    <li><a href="">Link 4</a></li>
                    <li><a href="">Link 5</a></li>
                    <li><a href="">Link 6</a></li>
                    <li><a href="">Link 7</a></li>
                </ul>
            </li>
            <li class="has_children"><a href="">Link</a>
                <ul class="sub-menu">
                    <li><a href="">Link 1</a></li>
                    <li><a href="">Link 2</a></li>
                </ul>
            </li>
            <li><a href="">Link</a></li>
            <li><a href="">Link</a></li>
            <li><a href="">Link</a></li>
        </ul>
    </nav>

CSS

body {
padding: 0;
margin: 0;
}

#topMenu {
height: 50px;
width: 100%;
background-color: #cde;
display: block;
}

nav {
width: 100%;
height: auto;
display: block;
margin: 0;
padding: 0;
}

nav a {
text-decoration: none;
padding-left: 40px;
padding: 20px 40px;
display: block;
}

nav ul {
list-style: none;
display: block;
margin: 0;
padding: 0;
background-color: #ccc;
} 

nav ul li {
display: block;
width: 100%;
border-top: 2px solid #abc;
}

nav ul ul {
overflow: hidden;
padding-top: 0px;
}

nav ul ul li a {
padding-left: 100px;
}

ul.sub-menu{
    display: none;
}
.has_children > a{
    color: #ddd;
}

JS:

var $menu_with_children = $('.has_children > a');

$menu_with_children.on('click', function(e){
    e.preventDefault();
    var $this = $(this);
    if (!$this.parent().find('> .sub-menu').hasClass('visible')) {
        $this.parent().find('> .sub-menu').addClass('visible').slideDown('slow');
    } else{
        $this.parent().find('> .sub-menu').removeClass('visible').slideUp('slow');
    }
});