Better jquery mega-menu tutorial

    My earlier simple mega menu implementation post displayed some simple css and jquery to explode a standard navigation menu into a mega-menu… I’ve made it even better. My biggest issue with that implementation was that it did not keep the order like you’d expect. It read left to right in columns rather than down each column. In the example you can see the first column of three would read from the top: a, d, g, j… this could potentially be confusing. So I wanted to update it to keep the order better and just stack the columns of elements rather than the elements themselves.

    I used some different jquery to execute this. First we walk through the menu elements and calculate which column they should be in. We basically map that element’s (li)index to the column it should be, some big math. Luckily I had some experience from actionscript in my arsenal doing just that, so porting the function to javascript I was ready to go. If your number X falls between A and B, and you would like to convert it to Y which falls between C and D follow this formula: Y = (X-A)/(B-A) * (D-C) + C. Plugging this function in and cancelling out the zeros and adding some rounding to get integers I got: Math.floor((liindex / $total * $cols)+1). Using this I added a class to each ‘li’ designating which column it should be in, and then used wrapAll to wrap them into column divs. Very simple and a much better implementation overall anyways. Better code, better user experience… what more can you ask… so here’s the example and jquery code. I’m thinking I should make this into a jquery plugin or something, any thoughts?

    better-mega-menu-screenshot

    See the mega menu in action

    Javascript code

    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;
                $rows = Math.ceil($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 your number X falls between A and B, and you would like to convert it to Y which falls between C and D follow this formula: Y = (X-A)/(B-A) * (D-C) + C.
                    jQuery(this).addClass('col-' + Math.floor((liindex / $total * $cols)+1) );
                    if( (liindex+1) % $rows == 0) {
                        jQuery(this).addClass('last');
                    }
                });

                for (var colcount = 1; colcount<= $cols; colcount++){
                    jQuery(this).children('.col-'+colcount).wrapAll('<div class="col" />');
                }
            }
        });
    });

    css

    ul { list-style:none; }

    /********** < Navigation */
    .nav-container { float:left; background: #398301; 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 #1b3f00; }
    #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 #1b3f00; border-width: 0 1px 2px 1px; background:#398301; 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 #1b3f00; border-bottom:1px solid #1b3f00; background:#398301; }
    #nav ul li a:hover { color:#fff !important; text-shadow: 1px 1px 3px #ccc; background: #2b6301; }
    #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: #1b3f00; }
    #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: #1b3f00; }

    /* 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; }

    Download

    Visit this demo page and view source or save as…

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

    3 Comments

    1. JavaFlactionscript
      Posted July 14, 2010 at 2:36 pm | Permalink

      Hey! I love the new design, it looks great. And I’m talking about both the blog and the menu. You’re my hero.

    2. Posted October 7, 2010 at 1:25 am | Permalink

      First of all, thanks for the code, been looking for 2 days.

      The code works well but I cant seem to get Magento to read the Javascript. I’ve placed the jquery.js and script everywhere and magento still cant seem to find it. At least that’s what I assumed as the category just wont move to the next column after added more than 10 of them.

      Any idea where’s the right place to place the script?

      • Posted October 7, 2010 at 2:39 pm | Permalink

        @Ashton – it looks like you’ve solved the issue? I was going to suggest that the css may be conflicting with something in your theme.

    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...