Some times we have to show Menu or Navigation Bar with dynamic items. Because of various screen resolutions like Mobile and PC the Menu Items might be hidden or overflown. To avoid disturbance with User Interface,  it is better to move overflown menu items to MORE option. In this article I am going to explain how can we make Responsive Menu or Navigation Bar by moving overflown elements to MORE option.

How it works :

  1. Calculate total-width of Navigation Bar or Menu
  2. Calculate summation of individual widths of Menu Items by iterating them.
  3. Find the overflown elements by comparing widths.
  4. Add overflown elements to More Option.
Observe the below  Markup and CSS. This Markup needs more than 1000px width to display. If your screen resolution is less then Menu Items will be overflown. 

Markup :

<ul id="horizontal">
<li><a href="#">item 1</a></li>
<li><a href="#">item 2</a></li>
<li><a href="#">item 3</a></li>
<li><a href="#">item 4</a></li>
<li><a href="#">item 5</a></li>
<li><a href="#">item 6</a></li>
<li><a href="#">item 7</a></li>
<li><a href="#">item 8</a></li>
<li><a href="#">item 9</a></li>
<li><a href="#">item 10</a></li>
<li><a href="#">item 11</a></li>
<li><a href="#">item 12</a></li>
<li><a href="#">item 13</a></li>
<li><a href="#">item 14</a></li>
<li><a href="#">item 15</a></li>
<li><a href="#">item 16</a></li>
<li><a href="#">item 17</a></li>
<li><a href="#">item 18</a></li>
<li><a href="#">item 19</a></li>
</ul>

CSS :

ul#horizontal, #horizontal ul  {
list-style-type: none;
margin: 0;
padding: 0;
}

#horizontal li {
float: left;  
}
#horizontal {
height: 50px;
float: left;
width:100%;
}
#horizontal a:visited {
font-weight: bold;
background-color: #98bf21;
text-align: center;
text-decoration: none;
text-transform: uppercase;
}
#horizontal a:link, div.horizontal a:visited {
font-weight: bold;
background-color: #98bf21;
text-align: center;
text-decoration: none;
text-transform: uppercase;
}
#horizontal a {
display: block;
line-height:50px;
  padding:38px 36px;
    color: #6e6e6e;
    font: bold 12px Helvetica, Arial, sans-serif;
    text-decoration: none;
    text-shadow: 0 1px 0 #fff;
    -webkit-transition: border-color .218s;
    -moz-transition: border .218s;
    -o-transition: border-color .218s;
    transition: border-color .218s;
    background: #f3f3f3;
    background: -webkit-gradient(linear,0% 40%,0% 70%,from(#F5F5F5),to(#F1F1F1));
    background: -moz-linear-gradient(linear,0% 40%,0% 70%,from(#F5F5F5),to(#F1F1F1));
    
}

#horizontal a:hover {
color: #333;
border-bottom:3px solid rgb(1,202,255);
padding-bottom:35px;
}

#horizontal li.hideshow ul{
position:absolute;
background: #f3f3f3;
display:none;
left:0px;
}

#horizontal li.hideshow
{
position:relative;
}

jQuery :

$(function() {
    alignMenu();

    $(window).resize(function() {
        $("#horizontal").append($("#horizontal li.hideshow ul").html());
        $("#horizontal li.hideshow").remove();
        alignMenu();
    });

    function alignMenu() {
        var w = 0;
        var mw = $("#horizontal").width() - 150;
        var i = -1;
        var menuhtml = '';
        jQuery.each($("#horizontal").children(), function() {
            i++;
            w += $(this).outerWidth(true);
            if (mw < w) {
                menuhtml += $('<div>').append($(this).clone()).html();
                $(this).remove();
            }
        });
        $("#horizontal").append(
                '<li  style="position:relative;" href="#" class="hideshow">'
                        + '<a href="#">more '
                        + '<span style="font-size:13px">&#8595;</span>'
                        + '</a><ul>' + menuhtml + '</ul></li>');
        $("#horizontal li.hideshow ul").css("top",
                $("#horizontal li.hideshow").outerHeight(true) + "px");
        $("#horizontal li.hideshow").click(function() {
            $(this).children("ul").toggle();
        });
    }
});

DEMO - Menu DEMO - Responsive Menu With MORE Option With jQuery

Hide More element if you have less items

This code was updated as for Vrajesh Dave the one who commented below. If you have less items to show then More element won't be have any children. So hide the More element if it is doesn't contain any children items. The modified alignMenu function will be
function alignMenu() {
    var w = 0;
    var mw = $("#horizontal").width() - 150;
    var i = -1;
    var menuhtml = '';
    jQuery.each($("#horizontal").children(), function() {
        i++;
        w += $(this).outerWidth(true);
        if (mw < w) {
            menuhtml += $('<div>').append($(this).clone()).html();
            $(this).remove();
        }
    });
    $("#horizontal").append(
            '<li  style="position:relative;" href="#" class="hideshow">'
                    + '<a href="#">more '
                    + '<span style="font-size:13px">&#8595;</span>'
                    + '</a><ul>' + menuhtml + '</ul></li>');
    $("#horizontal li.hideshow ul").css("top",
            $("#horizontal li.hideshow").outerHeight(true) + "px");
    $("#horizontal li.hideshow").click(function() {
        $(this).children("ul").toggle();
    });
    if (menuhtml == '') {
        $("#horizontal li.hideshow").hide();
    } else {
        $("#horizontal li.hideshow").show();
    }
}

9 comments:

  1. hi there ....i have 6 items to show ..but when there is no link to show item in more link how to hide more link........?

    ReplyDelete
    Replies
    1. If More element doest have any children elements then you can hide that Element..Here you need to change alignMenu fucntion. I have added one more code block above regarding to this

      Delete
  2. how can i add sub for this menu???

    ReplyDelete
  3. I made one using AngularJS and UI Bootstrap
    http://codepen.io/wessam/pen/PGoPpv

    ReplyDelete
  4. For better result on how the more button should appear please update with this.
    var mw = $("#horizontal").parent().width() -150 ; /* will adjust to the container in which its placed */
    or
    var mw = $(document).width() -150 ; /* Will check width of HTML document */

    ReplyDelete
  5. Since the "more" element is removed in the resize event handler, we can optimise the "don't show more if not needed" pattern a little more... The revised script adds the li hideshow element, and then hides it if it has no content. Why add the element at all?

    (html angle brackets replaced with square braces is snippet below)

    function alignMenu() {
    var w = 0;
    var mw = $("#horizontal").width() - 150;
    var i = -1;
    var menuhtml = '';
    jQuery.each($("#horizontal").children(), function() {
    i++;
    w += $(this).outerWidth(true);
    if (mw < w) {
    menuhtml += $('[div]').append($(this).clone()).html();
    $(this).remove();
    }
    });
    if (menuhtml != '') // nothing to show, so don't show it.
    {
    $("#horizontal").append(
    '[li style="position:relative;" href="#" class="hideshow"]'
    + '[a href="#"]more '
    + '[span style="font-size:13px"]↓[/span]'
    + '[/a][ul]' + menuhtml + '[/ul][/li]');
    $("#horizontal li.hideshow ul").css("top",
    $("#horizontal li.hideshow").outerHeight(true) + "px");
    $("#horizontal li.hideshow").click(function() {
    $(this).children("ul").toggle();
    });
    }
    }

    ReplyDelete

Blogroll

Follow this blog by Email

Popular Posts