jQuery: vertically animated sliding menu

Today I was working on a WordPress site and I stumbled on an interesting jQuery plugin used by the current theme. The plugin in question is called iconmenu and creates a vertical sliding effect on menu items. So I decided to recreate the main effect with less code. Let's see what I've done.

We start with this basic markup:

<ul id="test" class="slide-menu">
    <li>
        <div class="box-top">
            Lorem ipsum dolor
        </div>
        <div class="box-hover">
            Sit amet nescio
        </div>
    </li>
    <li>
        <div class="box-top">
            Lorem ipsum dolor
        </div>
        <div class="box-hover">
            Sit amet nescio
        </div>
    </li>
    <li>
        <div class="box-top">
            Lorem ipsum dolor
        </div>
        <div class="box-hover">
            Sit amet nescio
        </div>
    </li>
</ul>
​

To prepare the effect of the vertical sliding between the two boxes contained within each list item, we have to use contextual CSS positioning and hide the overflowing content:

ul.slide-menu {
    width: 90%;
    height: 10em;
    margin: 1em auto;
    padding: 0;
    list-style: none;
}

ul.slide-menu li {
    float: left;
    width: 30%;
    margin-right: 1em;
    height: 100%;
    background: #ccc;
    position: relative;
    overflow: hidden;
    cursor: pointer;
}

ul.slide-menu div.box-top {
    width: 100%;
    height: 100%;
    line-height: 10;
    text-align: center;
    position: absolute;
    top: 0;
    left: 0;
}

ul.slide-menu div.box-hover {
    width: 100%;
    height: 100%;
    line-height: 10;
    text-align: center;
    position: absolute;
    top: 10em;
    left: 0;
    background: #000;
    color: #f96;
}
​

The box with class box-hover has been hidden due to the top offset which is equal to the container's height. Since the container won't show its overflowing content, then our box won't be visible.

With jQuery we need to associate the hover() event with each list item. When the mouse enter on the item's area, we change the top offsets of each child box so that the first box is hidden and the second one is shown (and vice versa).

To add some additional easing effect, we're going to use the Easing plugin (alternatively, you can use the easing effects provided by jQuery UI):

var SlideMenu = new function() {

    var menu = $('#test'),
        items = $('li', menu);

    var hoverize = function() {
        items.each(function() {

            var $li = $(this);
            var boxTop = $('div.box-top', $li);
            var boxHover = $('div.box-hover', $li);

            $li.hover(function() {

                boxTop.stop(true, true).animate({
                    top: -$li.height()


                }, 500, 'easeOutExpo', function() {

                    boxHover.stop(true, true).animate({

                        top: 0
                    }, 500, 'easeOutExpo');

                });

            }, function() {

                boxTop.stop(true, true).animate({
                    top: 0


                }, 500, 'easeOutExpo', function() {

                    boxHover.stop(true, true).animate({

                        top: $li.height()
                    }, 500, 'easeOutExpo');

                });

            });

        });

    };

    this.init = function() {

        hoverize();
    }

}();

SlideMenu.init();

You can see the demo below.

Demo

Live demo

Back to top