A simple mega menu implementation with CSS and jquery

    I’ve been skinning quite a few ecommerce sites with the magento platform and wanted a simple way to explode the navigation menus. Some sites end up getting a long list of categories and sub-categories, so I wanted to do a mega-menu style navigation. One way to do it was to rewrite the html code for the navigation and pop each column into another nested unordered list. I’m not a fan of doing this because one – I didn’t want to manipulate the html. I like the simplicity of ul navigation with a clear flat list of li elements. Of course for nested sub-navigation any li can contain another ul. I wanted to just use some css and maybe javascript to visually accomplish the same thing. I also wanted it to be portable, so I could take it and use it on a wordpress install or even a plain html site. I went to my favorite: jquery. I knew there was a likely plugin out there already that would do something similar, but nothing after my initial search, but I realized that it was a simple procedure and mostly accomplished with some css.
    mega menu screenshot
    I’ll walk you through the process here and let you inspect the code yourself and see it in action on the demo page. Assign each ul to be a default width of 15em, then each li element we float:left and also give it a width of 15em. This way we can change the ul width to 30em and automatically I have 2 columns! Assigning the nested ul a specific width according to it’s class is done through css, mm-0 will be 15em and incrementally each next one will be 15em more. mm-1 is 30 and mm-2 is 45. Then we use jquery to determine the number of elements in the list and assign it a class accordingly. This involves some math and some preferences. Using the magic ui number 7, I determined that a menu with more than 7 elements should explode into multiple columns. So anything less than or equal to 7 I assign the class ‘mm-1′ which in the css sets the width to the standard 15em (ie 1 mega menu column). More than 7 should pop into columns no more than 8 tall. So dividing the total by 8 will give us the number of columns we want. We’ll add a class of mm-x, where x would be the number of columns. And the li elements will float to the left and fill in the space in columns.
    One specific issue is the last element in the menu, sometimes we need to style that element differently. I’ll loop through each child of the nested ul element and if it is on the bottom row apply a class of ‘last’. But this was a little tricky in calculating which would be last because were never sure how many elements there will be or how many columns. I just used the remainder after dividing the total by the number of columns, then if the remainder could be used to know which elements are on the bottom row.

    OK, now that that’s out of the way, let’s look at the code.

    HTML

    This I won’t show, you can inspect the source of the demo if you wish to see it, it a basic nested collection of unordered lists. It’s the standard that is created by magento, wordpress and most other CMS platforms.

    CSS

    html, body { margin:0; padding:0; }
    ul { list-style:none; }

    /********** < Navigation */
    .nav-container { float:left; background: #186C94; margin: 10em 0; width: 960px; }
    #nav { border: 0px none; padding:3px 0 2px 44px; margin:0; font-size:13px; }

    /* All Levels */
    #nav li { text-align:left; position:relative; }
    #nav li.over { z-index:999; }
    #nav li.parent {}
    #nav li a { display:block; text-decoration:none; }
    #nav li a:hover { text-decoration:none; }
    #nav li a span { display:block; white-space:nowrap; cursor:pointer; }
    #nav li ul a span { white-space:normal; }

    /* 1st Level */
    #nav li { float:left; }
    #nav li a { float:left; padding:5px 10px; font-weight:normal; color: #fff; text-shadow: 1px 1px #111; }
    #nav li a:hover { color: #fff; text-shadow: 1px 1px 3px #ccc; }
    #nav li.over a,
    #nav li.active a { color:#fff; }

    /* 2nd Level */
    #nav ul { position:absolute; width:15em; top:26px; left:-10000px; border:1px solid #104A65; border-width: 0 1px 2px 1px; background:#186C94; padding: 6px 0 6px; }
    #nav ul div.col { float:left; width: 15em; }
    #nav ul li { float:left; padding: 0; width: 15em; }
    #nav ul li a { float:none; padding:6px 9px; font-weight:normal; color:#FFF !important; text-shadow: 1px 1px #111; border-bottom:1px solid #104A65; background:#186C94; }
    #nav ul li a:hover { color:#fff !important; text-shadow: 1px 1px 3px #ccc; background: #135575; }
    #nav ul li.last > a { border-bottom:0; }
    #nav ul li.last.parent > a { border-bottom:0; }

    #nav ul li.over > a  { font-weight:normal; color:#fff !important; background: #104A65; }
    #nav ul.mm-1 { width: 15em; }
    #nav ul.mm-2 { width: 30em; }
    #nav ul.mm-3 { width: 45em; }
    #nav ul.mm-4 { width: 60em; }
    /* 3rd+ leven */
    #nav ul ul { top:-6px; background: #104A65; }

    /* Show Menu - uses built-in magento menu hovering */
    #nav li.over > ul { left:0; }
    #nav li.over > ul li.over > ul { left:14em; }
    #nav li.over ul ul { left:-10000px; }

    /* Show Menu - uses css only, not fully across all browsers but, for the purpose of the demo is fine by me */
    #nav li:hover > ul { left:0; z-index: 100; }
    #nav li:hover > ul li:hover > ul { left:14em; z-index: 200; }
    #nav li:hover ul ul { left:-10000px; }

    Javascript

    Don’t forget to include jQuery (I prefer using the google hosted version at http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js)

    jQuery(document).ready(function() {
        //clean up the row of the mega menu. add css class to each element on bottom row.
        //only if more than 7 elements. if more than 16, mm-3
        jQuery('#nav li ul').each(function(ulindex, ulele){
            $total = jQuery(this).children('li').size();
            if ($total <= 7) {
                jQuery(this).addClass('mm-1');
            }
            else {
                $cols = Math.floor(($total) / 8) + 1;
                $remainder = $total % $cols;
                jQuery(this).addClass('mm-' + $cols + ' total-' + $total + ' rem-'+$remainder );

                jQuery(this).children().each(function(liindex, liele){
                    //alert("total: "+$total+", remainder: "+ $mod+", ulindex: "+ulindex+", liindex: "+liindex);
                    if( liindex + $remainder >= $total || $remainder == 0 && liindex + $cols >= $total ){
                        //alert("total: "+$total+", remainder: "+ $remainder+", index: "+liindex);
                        jQuery(this).addClass('last');
                    }
                });
            }
        });

    });

    See the demo in action

    This entry was posted in tutorial and tagged , , , , , , , , , , , , , , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

    9 Comments

    1. handoyo
      Posted July 15, 2010 at 1:21 pm | Permalink

      Hello,thanks for the tutorial you provide..Are there any chance of providing an example how to use it?Thanks a lot..

    2. handoyo
      Posted August 2, 2010 at 10:08 am | Permalink

      What i mean is how to implement it magento.. :d
      Do i just have to change the css files only?Thanks…

      • Posted August 2, 2010 at 12:11 pm | Permalink

        You’ll need to update the css as well as add the javascript listed here. Note that it uses jquery, so you’ll have to include that as well. All that depends on the theme/skin setup, I usually add the js references to the page.xml file and create a new js file specific for my theme to put all my jquery into. Good luck!

    3. handoyo
      Posted August 2, 2010 at 10:36 pm | Permalink

      Ok,thanks a lot Evan..

    4. Posted March 22, 2011 at 2:28 pm | Permalink

      This absolutely DOES NOT work in Internet Explorer. Beware!

      • Posted March 23, 2011 at 6:47 pm | Permalink

        @Liz – Can you be helpful and let us know what version of IE you’re complaining about? And what OS? Thanks! It worked when I posted it in all the major browsers, although they have all issued major releases in the past couple weeks so things may have changed, thanks in advance!

        • John
          Posted April 1, 2011 at 4:08 am | Permalink

          Got the same issue. Its not working on IE8

    5. rafael
      Posted November 21, 2011 at 3:40 pm | Permalink

      DOES NOT work in Internet Explorer

    3 Trackbacks

    1. By Better jquery mega-menu tutorial | circlecube on July 14, 2010 at 1:32 pm

      [...] earlier simple mega menu implementation post displayed some simple css and jquery to explode a standard navigation menu into a [...]

    2. [...] Simple mega menu implementation with CSS and jquery – Source +108 Free CSS Menu Designs {Mega Menu, Dropdown, Horizontal, Vertical}” [...]

    3. [...] simples menu mega com CSS e jQuery - Fonte Implementação simples menu mega com CSS e [...]

    Post a Comment

    Your email is never published nor shared. Required fields are marked *

    *
    *

    You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

    • Recent Posts

      Synth Emulator on Google Japan Doodle Today

      Synth Emulator on Google Japan Doodle Today Embedded Link Moog 自分のオリジナル曲を創って、 #moogdoodle で共有しよう。 Tweet

      WordPress updates plugin directory

      New additions to the plugin directory include: favorites, incorporating support forums into it's own tab for each plugin as well as support stats being displayed! Great! I think we also need the ability to give plugins ratings and reviews (bonus points if it can be done from within a wordpress admin dashboard when installing plugins). [...]

      Short Head

      Use zipf's short head to tune your website rather than redesign the whole thing. To make a website successful it needs to meet the needs of the users. Find out what those needs are by using the short head philosophy to equate most searched things as the biggest needs of the users. Use personas to [...]

      Img Set?

      Great article at a list apart discusing the state of the industry regarding responsive images. This picks apart the set attribute of the img element from a surprisingly objective view coming from someone so close to the picture element. Insightful discussion about the principle behind the proposals than the actual solution too. If the working [...]

      Triudo

      A mesmerizing animated triangle-ish shape form. Embedded Link triduo triduo Tweet

      Git – the paradigm shift

      A great developer story about the differences on what Git is vs other version control and what Git is not. This is how we should learn it. I heard over and over that it was distributed, but never grasped what that meant, so here are a few links and explanations that will help unlearn version [...]

      Tweening Lib comes to Javascript!

      I'm very excited to share the news that the tween library from GreenSock (hands down the best tweening library I used in flash) is not ported for use in javascript! This will be great! I missed that simple syntax from as3 when animating javascript, and now I can have my cake and eat it too. [...]

      Responsive CSS Tricks

      Here are a few useful css tricks to remember when building responsive design sites from web designer wall Embedded Link 5 Useful CSS Tricks for Responsive Design Making the design to be responsive is very easy as shown in my Responsive Design in 3 Steps tutorial, but maintaining the elements to look aesthetically balanced on [...]

      Picture element of srcset attribute?

      Bruce details the reasons and story behind the srcset attribute which is now introduced as an alternative to the picture element. Some aspects of the attribute are nice (like the fact that it's an attribute and not a new element, so it's creating up new elements with for problems. It's adapting currently used elements to [...]

      SVG Preloader with Raphael JS

      Here's a very creative use of using a newly available technology. Using svg graphics which are very lightweight, for a website preloader. I like the animation used as well. Embedded Link Make a stylish preloader with SVG | Tutorial | .net magazine Many sites neglect users with slow connections. Ian Culshaw explains how to use [...]

    • Recent Comments

      Bruce Brownlee

      Bruce Brownlee

      Ah IE6. I'd have 2 more years of sleep without IE6. Margin doubling, no properties,...
      versaena

      versaena

      how to give color at runtime…… thank you
      Mobile Websites

      Mobile Websites

      I disagree, mobile websites are the future – desktop websites and mobile websites...
      Matt Fasick

      Matt Fasick

      That's cool. I like the ripple effect as well.
      Nico

      Nico

      hi! really great job guy! very impressive.. just a question… do u have a solution to do a refresh...
      Evan Mullins

      Evan Mullins

      Agreed! I've just seen some people get pretty heated about separating all functionality...