Advertisement
  1. Code
  2. JavaScript
  3. jQuery

Creating a Drop-Down Menu for Mobile Pages

Scroll to top

This tutorial will teach you how to create and animate a hamburger menu icon and then attach an event listener through jQuery for triggering a drop-down menu.

I will be using Jade (Pug) and Sass instead of vanilla HTML and CSS. So you should at least have a basic knowledge of these templating engines.

Creating the Playground

We will start with the implementation of a simple playground. I will only be providing the Jade template along with Sass styling, since this is not the scope of the tutorial. You can take it and use it or you can come up with your own design.

Jade file:

1
body
2
    #container

3
        #header

4
        #body

5
            .content
6
                .left
7
                .right
8
                    - for (i=1; i <= 5 ; i++ )
9
                        div( id="text" + i )
10
            .content
11
                .left
12
                .right
13
                    - for (j=6; j <= 10 ; j++ )
14
                        div( id="text" + j )
15
            .content
16
                .left
17
                .right
18
                    - for (k=11; k <= 15 ; k++ )
19
                        div( id="text" + k )

Sass file:

1
=flex()
2
  display: -webkit-box
3
  display: -moz-box
4
  display: -ms-flexbox
5
  display: -webkit-flex
6
  display: flex
7
  
8
=transition($time)
9
  -webkit-transition: all $time ease
10
  -moz-transition: all $time ease
11
  -ms-transition: all $time ease
12
  -o-transition: all $time ease
13
  transition: all $time ease
14
15
html, body
16
  margin: 0
17
  padding: 20px 0
18
  +flex()
19
  justify-content: center
20
21
//----------------------------------//
22
23
#container
24
  width: 320px
25
  height: 550px
26
  background-color: #ebebeb
27
  overflow: hidden
28
29
#header
30
  height: 45px
31
  background-color: #9b9b9b
32
  position: relative
33
34
35
#body
36
  padding: 0 20px
37
  padding-top: 40px
38
  +flex()
39
40
  flex-direction: column
41
  justify-content: flex-start
42
43
.content
44
  +flex()
45
46
  flex-direction: row
47
  justify-content: flex-start
48
  margin-bottom: 25px
49
50
51
  .left
52
    width: 100px
53
    height: 100px
54
    margin-right: 15px
55
    background-color: #e1e1e1
56
57
  .right
58
    @for $i from 1 through 15
59
      #text#{$i}
60
        margin-top: 10px
61
        width: 50 + random(100) + px
62
        height: 10px
63
        background-color: #e1e1e1

Note: Here I created two mixins named flex and transition. Mixins make it easier to reuse some CSS rules by grouping them. Whenever I need to add display:flex with all vendor prefixes, I can just use +flex() instead, thanks to the mixin.

We will use this structure and build upon it for the rest of the tutorial.

The final result should look like this:

PlaygroundPlaygroundPlayground

View the current code

Hamburger Menu Icon

Now it is time to create a simple yet attractive hamburger menu and animate it through CSS.

Add a new div inside #header and name it #hamburger. Then create two children divs inside #hamburger. They should have a common class and individual IDs.

1
#hamburger

2
    .strip#top
3
    .strip#bottom

Now we need to style the parent #hamburger div and the children divs with the common class of .strip.

1
#hamburger
2
  height: 100%
3
  width: 45
4
  +flex()
5
6
  flex-direction: column
7
  justify-content: space-between
8
  padding-left: 20px

We set the height of the div equal to its parent div, which is #header, by defining the height: 100%. Also, we set a width value for this parent div, which will define its "clickable" region.

Next, we add flexbox with all vendor prefixes by using mixins, which we created earlier.

Since we want our .strip divs to be positioned vertically, we set flex-direction: column and then use justify-content: space-between in order to put space in between the .strip divs.

Then we need to push those divs towards each other by adding bottom and top padding to the respective divs.

1
#top
2
  margin-top: 17px
3
  
4
#bottom
5
  margin-bottom: 17px

We also added padding-left: 20px in order to move the .strip divs further to the right.

The next thing is to style the strips. This is relatively easy by just defining the size and the color of the divs.

1
.strip
2
  width: 25px
3
  height: 2px
4
  background-color: #ffffff

The final result with the hamburger menu icon should look like this:

Hamburger Menu IconHamburger Menu IconHamburger Menu Icon

The next thing is to animate the menu icon so that when it is clicked, it should animate into a cross sign.

Animating the Hamburger Menu Icon

At this point, we are going to use basic jQuery to toggle some CSS classes.

Let's first create the CSS classes to be toggled.

We are going to utilize the translate and rotate settings of the transform property of CSS along with the transition property.

First, add transitions to both the #top and #bottom divs by using mixins with a specific timing parameter.

1
#top
2
  margin-top: 17px
3
  +transition(.25s)
4
5
#bottom
6
  margin-bottom: 17px
7
  +transition(.25s)

Now we need to define the styling of the classes to be toggled.

We will be rotating and translating each .strip div individually, so we need to toggle different classes both for the #top and #bottom divs.

1
#top
2
  margin-top: 17px
3
  +transition(.25s)
4
5
  &.topRotate
6
    transform-origin: center
7
    transform: translateY(4px) rotateZ(45deg)
8
9
#bottom
10
  margin-bottom: 17px
11
  +transition(.25s)
12
13
  &.bottomRotate
14
    transform-origin: center
15
    transform: translateY(-5px) rotateZ(-45deg)

Here we defined the styling for two different classes named .bottomRotate and .topRotate, which will be added to and removed from their respective reference divs, #top and #bottom.

Note that different sizing of the .strip class would result in a need for different translateY and rotateZ values in order to animate into a proper cross sign.

Class Toggling With jQuery

We defined how each .strip div will animate when the topRotate and bottomRotate classes are present. However, we have yet to attach an event listener to toggle those classes.

Create a new JavaScript file and use the following code to toggle the topRotate and bottomRotate classes to divs with #top and #bottom IDs respectively.

1
$(document).ready(function(){
2
  $("#hamburger").click(function(){
3
      $("#top").toggleClass("topRotate");
4
      $("#bottom").toggleClass("bottomRotate");
5
  });
6
})

We put all our code inside $(document).ready(function(){}) in order to wait for the whole page to be loaded before taking any action. 

When we click the #hamburger div, it will toggle the classes for divs with specific IDs.

Note: Do not forget to add the jQuery source file into your project.

View the current code

Creating the Menu List

The next step is to create a menu with list items.

Use the following structure under the #header:

1
#dropDown
2
    #background
3
    ul
4
        li Home
5
        li Blog
6
        li Projects
7
        li Authors
8
        li Jobs
9
        li Contact

So here we used the ul tag as the parent in order to group the items with li tags as children. Moreover, in order to create an expanding background animation, we also added a div with the ID of #background.

Let's style the ul and li elements first.

1
ul
2
  list-style: none
3
  padding: 0
4
  margin: 0

Set the list-style to none in order to remove the bullets from the ul elements and also set both padding and margin to 0 in order to remove all predefined values.

Now style the li elements:

1
li
2
    //display: none
3
    background-color: #9b9b9b
4
    color: #ffffff
5
6
    font-family: 'Quicksand', sans-serif
7
    font-weight: lighter
8
    font-size: 15px
9
    padding: 20px
10
    padding-left: 60px
11
12
    &:after
13
      position: absolute
14
      content: ''
15
      left: 60px
16
      width: 60%
17
      height: 1px
18
      bottom: 4px
19
      background: rgba(255, 255, 255, 0.25)
20
21
    &:last-child:after
22
      width: 0

Here I commented out the display:none in order to be able to see the result. However, when animating, we will use it to hide the list elements initially.

I also added the after pseudo-element and styled it accordingly in order to separate each li element with a straight line. :last-child:after removes this line for the last li element.

View the current code 

Animating the Menu List

Now we are going to use some Sass control directives in order to add CSS keyframe animations with different attributes to each li element.

1
@keyframes drop
2
  0%
3
    opacity: 0
4
    transform: scale(1.3)
5
6
  100%
7
    opacity: 1
8
    transform: scale(1)
9
    
10
@keyframes fold
11
  0%
12
    opacity: 1
13
    transform: scale(1)
14
15
  100%
16
    opacity: 0
17
    transform: scale(0.7)

Here we defined our keyframe animations drop and fold.

drop is for animating the opening of the menu list. The initial scaling is 30% more, and it scales back down to the original size as the transparency goes from 0 to 1. The opposite action takes place in fold.

Now we need to attach those keyframes to li elements. This part is where the Sass comes in handy.

1
@for $i from 1 through 6
2
  li:nth-child(#{$i})
3
    animation:
4
      name: fold
5
      duration: 80ms*(6-$i) + 1ms
6
      timing-function: ease-in-out
7
      fill-mode: forwards
8
9
  li.anim:nth-child(#{$i})
10
    animation:
11
      name: drop
12
      duration: 100ms*$i
13
      timing-function: ease-in-out
14
      fill-mode: forwards

Here I used a for loop that goes from 1 to 6 with the index of $i.

Now we need to use this index to attach each animation to li elements with different durations.

First, consider the li.anim:nth-child(#{$i}) line.

Here we are grabbing the $ith child of the li element with class of anim.

We will be toggling this anim class. So, when it is added to li elements, the keyframe animation with the name of drop will take action. When it is removed, the fold animation will take action.

The next important thing is the duration attribute.

duration: 100ms*$i for the drop animation is extending the duration of the animation for each incrementing child number. So, when this code is compiled, the first li child will have duration: 100ms, and the last child will have duration: 600ms.

This will give the sense of animating each element one after another.

We do the same thing for the fold animation. This time, the last element should be animated faster, hence duration: 80ms*(6-$i) + 1ms. The 1ms added to the duration is due to the fact that when you set the duration to 0, some problems are likely to occur, and your animation might not work properly.

When we were styling the li element, I mentioned that we needed to use display:none in order to avoid undesired animation playing. If you don't set it to none, you will see that the fold animation plays once when the page is loaded.

If we set the display property to none, we won't see that, and then we need to show the li element before toggling the anim class.

We want our animations to play when we click the hamburger icon. So let's use some jQuery to set the display property of each li item to block and also toggle the anim class.

1
$(document).ready(function(){
2
  $("#hamburger").click(function(){
3
      $("#top").toggleClass("topRotate");
4
      $("#bottom").toggleClass("bottomRotate");
5
6
      $("li").show();
7
      $("li").toggleClass("anim");
8
9
  });
10
})

View the current code

You will notice that we can see the animation of each li element individually. However, we'd rather have an expanding menu feeling.

In order to fix that, we simply need to expand the height of a div. That div is #background, which we initially added when creating the ul and li elements.

1
#background
2
  width: 100%
3
  height: 0
4
  background-color: #9b9b9b
5
  position: absolute
6
  +transition(.45s)
7
8
  &.expand
9
    height: 550px

We will be toggling the expand class in order to set the height attribute to 550px within .45s. Note that I used the transition mixin to define the transition with a specific time parameter.

Final Result 

Conclusion

Throughout this tutorial, we practiced how to use for loops within HTML and CSS through the Jade and Sass templating engines. On top of that, we created CSS keyframe animations and attached them with different duration attributes to specific HTML elements. Then we toggled classes with jQuery to control those animations.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.