Simple Mega Menus with Beaver Builder and Beaver Themer

Heads Up!

We turned the below code into another awesome tool and chucked it into Beaver Team Pro. Plus we added keyboard navigation for accessibility and an even simpler configuration! Check out the Video on the Mega menu update.

Dont worry, the code below still works great.

I played with a million mega menu plugins over the years and they were all to complex or too simple to make it look good. So I ended up building my own.

These snippets of CSS/JS are all you need to add to your BB/Themer website to create awesome Mega Menus

Watch the video, and then steal the code :)

How it Works

  1. Add the ID my-mega-menu to your Beaver Builder menu.
  2. Create a Beaver Themer part, make it visible on the entire site.
  3. Create Rows inside the Themer part
    • For each menu item, create a Row and give the row a special ID. this is where the code does its magic
      • The code takes the menu item name, and looks for a lowercase version, with dashes for spaces, starting with "mega-"
      • Contact Us menu item would have an associated mega menu ID of mega-contact-us
      • About maps to mega-maps
      • Services -> mega-services
      • The code does the rest.

The JS:

To add JS sitewide:

  1. Open any page with Beaver Builder
  2. Click the title bar in the upper left corner to open the Tools menu, then click Global settings.
  3. On the JavaScript tab, enter this JavaScript code.
  4. Click Save.
// mega menu js

var menuElement = "#my-mega-menu .menu-item";
var mobileToggle = '.fl-menu-mobile-toggle';

jQuery(document).ready(function(){
  
    // exit if bb is running
    if(jQuery('body').hasClass('fl-builder-edit'))
        return true; 

    //add the helper parent class to the mega menu for mobile
    jQuery('[id^="mega-"]').first().parent().addClass('mega-mobile-container')


    //set top location of 
    jQuery(window).on('resize', function () {
        if(isMobile())// set init value
        {
            //set top value of container
            topValue = jQuery(mobileToggle).offset().top + jQuery(mobileToggle).outerHeight(); 
            jQuery('.mega-mobile-container').css('top',topValue + 'px');
            
        }
        else
        {
            jQuery('.mega-mobile-container').css('top','');
            jQuery('.show-mega-mobile').removeClass('show-mega-mobile');
            topValue = 0;
        }
        
        jQuery(menuElement).each(function(){

            var menuItem = jQuery(this);
            var megaItem = jQuery("#"+"mega-"+menuItem.text().replace(/\s/g , "-").toLowerCase());
            
            if(megaItem.length) // if its  mega anything
            {
                //set up hover listeners for menu items 
                menuItem.hover(function() {
                    if(!isMobile())
                    {
                        jQuery("#"+"mega-"+jQuery(this).text().replace(/\s/g , "-").toLowerCase()).addClass('show-mega');
                    }
                }, function() {
                    if(!isMobile())
                    {
                        jQuery("#"+"mega-"+jQuery(this).text().replace(/\s/g , "-").toLowerCase()).removeClass('show-mega');
                        
                    }
            });
            //the rest should be handled with CSS


                if(isMobile())
                {
                    megaItem.css('top',  topValue + 'px');
                    topValue += megaItem.height();
                }
                else
                {
                    jQuery('body').removeClass('show-mega-mobile');
                    topValue = menuItem.offset().top + menuItem.outerHeight();
                    megaItem.css('top',  topValue + 'px');
                }
            }
               
        });
    }).resize();
    
    jQuery(mobileToggle).click(function(event){
        event.preventDefault();
        event.stopPropagation();
       jQuery('body').toggleClass('show-mega-mobile');
    });

});

function isMobile(){
    return jQuery(mobileToggle).is(':visible');
}

The CSS:

To add CSS sitewide:

  1. Open any page with Beaver Builder
  2. Click the title bar in the upper left corner to open the Tools menu, then click Global settings.
  3. On the CSS tab, enter this CSS code.
  4. Click Save.
body:not(.fl-builder-edit) [id^="mega-"] {
    -webkit-transition: all 300ms ease-in-out;
    -moz-transition: all 300ms ease-in-out;
    -ms-transition: all 300ms ease-in-out;
    -o-transition: all 300ms ease-in-out;
    transition: all 300ms ease-in-out;
    z-index: 100;
}
.show-mega{
    visibility: visible !important;
    opacity: 1 !important;
}
body:not(.fl-builder-edit) [id^="mega-"]:hover {
visibility: visible !important;
opacity: 1 !important;
}
/* mobile stuffs */
body.show-mega-mobile [id^="mega-"]{
    visibility: visible !important;
    opacity: 1 !important;
}


/* small screens mega settings*/
@media (max-width: 767px){
    
    .mega-mobile-container{
        visibility: hidden;
        opacity: 0;
        position: fixed;
        top:150px;
        left: 0;
        bottom: 0;
        overflow-y: scroll;
        width: 100%;
        z-index: 100;
    }
    
    .show-mega-mobile .mega-mobile-container{
        visibility: visible !important;
        opacity: 1 !important;
    }
    
}
/* bigger screens mega settings*/
@media (min-width: 768px){
    
    body:not(.fl-builder-edit) [id^="mega-"] {
        visibility: hidden;
        opacity: 0;
        position: fixed;
        top:150px;
        left: 0;
        width: 100%;
    }    
    
    
}

18 Comments

  1. Ben on June 1, 2021 at 7:21 pm

    Hey there! I love this! So much simpler than some of those menus like Quad Menu.

    Any chance to consider revealing the dropdown on a click?

    https://css-tricks.com/in-praise-of-the-unambiguous-click-menu/

    • Tom on June 1, 2021 at 8:23 pm

      Thanks Ben!

      When you’re right, you’re right. I’ll update the code in the next few days for the unambiguous click.

  2. Craig on June 3, 2021 at 5:03 am

    Hi Tom.

    This is an excellent solution, thank you.

    I have a slight issue in that some of my menu items contain a question mark, which stops the mega menu from working.

    Is there any chance you could update the JS to allow for this please.

  3. Craig on June 3, 2021 at 9:51 am

    Also noticed another issue, I’m getting a gap above each subsequent mega menu…

    Here is a short clip of the issue – https://cln.sh/uFpkhDG1xdAURei758qI

    Unfortunately the site is only on local at the moment, but if you need any further info I can provide it.

  4. Tom on June 3, 2021 at 11:00 am

    Thanks Craig!

    I’ve updated the code to replace all non alphanumeric characters, so your ?’s and !’s should now be replaced with a single “-”

    Just FYI, the code is also updated to on click now, its much better UX than “on hover” 🙂

    I added the helper function megaDebug() so you can see what your mega menu row ID’s should be after being parsed. Just type megaDebug() into the console, and it will tell you the mega names.

    As for the other issue – I can’t really say without seeing it live. Its a good looking site though! Push it onto a server and send me a link, we’ll get it working for you 🙂

    • Craig on June 3, 2021 at 3:14 pm

      Wow! That’s fantastic Tom. Thank you.

      I have emailed you separately with a link and another query.

      Best regards,
      Craig

  5. Heather Steele on June 3, 2021 at 7:08 pm

    This is fantastic! I have been wanting to do just this on a few sites but didn’t have the time or brains to work it out — super excited!

    • Tom on June 8, 2021 at 9:56 am

      Awesome! Please share some links to some completed sites!

  6. Chris Smith on June 15, 2021 at 10:01 am

    Hi Tom –

    Fantastic contribution. Thanks!

    I have a small issue. See:
    https://vsbbusdir.wpengine.com/
    PLAN YOUR TRIP is the mega row and it works great…
    Except when you are on an actual directory listing.

    example:
    https://vsbbusdir.wpengine.com/business-listing/celebration-cruises/
    Now the click doesn’t load the menu rows.

    Can you take a quick look and help me figure it out?

    I am also using the Max Width columns plugin and it too is a great and very much appreciated solution.

  7. Greg on August 5, 2021 at 4:45 pm

    Hi Tom,
    I was using another Mega Menu solution and then found out that it’s really not accessible (specifically via keyboard navigation). Was wondering if your solution here is and if that includes any content in the menu or if it’s only links/button. I.e. if you tab to the top menu item the menu opens, and then you can tab/arrow through all the items in the menu before you tab on to the next top menu item, and so on?

    • Tom on September 16, 2021 at 10:44 am

      Hey Greg!
      This is not accessible as it stands but our next update will be specifically to make it *more* accessible – but definitely not perfect.

    • Tom on April 14, 2022 at 1:36 pm

      Hi Again Greg – If you want an accessible mega menu with keyboard nav, check out the Mega menu module in Beaver Team Pro. 🙂

  8. David on October 5, 2021 at 4:48 pm

    I love this mega-menu but I”m having a major problem with it and I can’t figure out a solution.

    When I load a page, the mega-menu isn’t visible but it’s sitting behind the regular content just below the menu and the items in my menu are still clickable. This interferes with other interactivity on the page. I would assume that the mega-menu should be positioned off-canvas until it’s needed?

  9. Martin on October 7, 2021 at 11:10 pm

    Great tutorial! Just curious what the JS was to make the menu apper on hover.

  10. Jonathan on October 20, 2021 at 4:32 am

    Love this, but appear to have a problem with too many spaces…

    “How We Help” is being offered as “mega-how-we help”

    See screenshot – https://snipboard.io/TtEO3V.jpg

  11. David on November 30, 2021 at 6:50 pm

    I’ve noticed that if I have a menu item that links to an anchor on the current page, the menu doesn’t disappear. Wondering if the code should hide the megamenu on *any* click.

    I tried replacing this IF statement:

    //click outside of mega menu
    jQuery(document).on(‘click’, function (e) {
    if (jQuery(e.target).closest(‘[id^=”mega-“], .mega-mobile-container’).length === 0) {
    if(jQuery(‘.show-mega, .show-mega-mobile’).length){
    jQuery(‘[id^=”mega-“]’).removeClass(‘show-mega’);
    jQuery(‘body’).removeClass(‘show-mega-mobile’);
    }
    }
    });

    with this:

    //click outside of mega menu
    jQuery(document).on(‘click’, function (e) {
    if(jQuery(‘.show-mega, .show-mega-mobile’).length){
    jQuery(‘[id^=”mega-“]’).removeClass(‘show-mega’);
    jQuery(‘body’).removeClass(‘show-mega-mobile’);
    }
    });

    It works, although I suspect there’s probably a better way.

  12. Chris on January 19, 2022 at 11:33 am

    Working nice! However I face an issue on menu items that have some unicode characters (language specific) – in my case Polish (ż, Ä…, Å‚). Any help in modifying the JS code to accommodate that?

  13. Bill on March 3, 2022 at 4:52 pm

    is Mobile Function wasn’t working for me so I switched it up a bit…

    // mega menu js
    // with love from https://sitespot.dev/simple-mega-menus-with-beaver-builder-and-beaver-themer/

    var menuElement = “#my-mega-menu .menu-item”;
    var mobileToggle = ‘.fl-menu-mobile-toggle’;

    jQuery(document).ready(function(){

    // exit if bb is running
    if(jQuery(‘body’).hasClass(‘fl-builder-edit’))
    return true;

    //add the helper parent class to the mega menu for mobile
    jQuery(‘[id^=”mega-“]’).first().parent().addClass(‘mega-mobile-container’)

    //set top location of
    jQuery(window).on(‘resize megamenurefresh’, function () {
    if(isMobile())// set init value
    {
    //set top value of container
    topValue = jQuery(‘header’).offset().top + jQuery(‘header’).outerHeight() – 20;
    jQuery(‘.mega-mobile-container’).css(‘top’,topValue + ‘px’);

    }
    else
    {
    jQuery(‘.mega-mobile-container’).css(‘top’,”);
    jQuery(‘.show-mega-mobile’).removeClass(‘show-mega-mobile’);
    topValue = 0;
    }

    jQuery(menuElement).each(function(){

    var menuItem = jQuery(this);
    var megaItem = jQuery(“#”+”mega-“+menuTitle(menuItem.text()));

    if(megaItem.length) // if its mega anything
    {
    //set up click listeners for menu items
    menuItem.off(‘click’).click(function(event) {
    console.log(‘click’);
    event.preventDefault();
    mm = jQuery(“#”+”mega-“+menuTitle(jQuery(this).text()));
    console.log(“#”+”mega-“+menuTitle(jQuery(this).text()));
    console.log(isMobile());
    console.log(mm.length);
    // if it has a mega menu
    if(mm.length && !isMobile())
    {
    console.log(“inside if”);
    event.preventDefault();
    event.stopPropagation();
    if(!mm.hasClass(‘show-mega’))
    {
    jQuery(‘.show-mega’).removeClass(‘show-mega’);
    mm.addClass(‘show-mega’);

    }
    else
    mm.removeClass(‘show-mega’);
    }

    });

    if(isMobile())
    {
    megaItem.css(‘top’, topValue + ‘px’);
    topValue += megaItem.height();
    }
    else
    {
    jQuery(‘body’).removeClass(‘show-mega-mobile’);
    topValue = jQuery(“header”).offset().top – jQuery(window).scrollTop() +jQuery(“header”).outerHeight();
    megaItem.css(‘top’, topValue + ‘px’);
    }
    }

    });
    }).resize();

    jQuery(mobileToggle).click(function(event){
    event.preventDefault(); // stop the inbuilt stuff from stuffin
    event.stopPropagation();
    jQuery(‘body’).toggleClass(‘show-mega-mobile’);
    });

    //close mega menu stuff

    // escape click
    jQuery(document).on(‘keyup’, function(e) {
    if (e.key == “Escape”)
    {
    jQuery(‘.show-mega’).removeClass(‘show-mega’);
    jQuery(‘body’).removeClass(‘show-mega-mobile’);
    }
    });

    //click outside of mega menu
    jQuery(document).on(‘click’, function (e) {
    if (jQuery(e.target).closest(‘[id^=”mega-“], .mega-mobile-container’).length === 0) {
    if(jQuery(‘.show-mega, .show-mega-mobile’).length){
    jQuery(‘[id^=”mega-“]’).removeClass(‘show-mega’);
    jQuery(‘body’).removeClass(‘show-mega-mobile’);
    }
    }
    });

    });

    //replace menuItem.text().replace(titleRegex,”-“).toLowerCase()
    function menuTitle(theText){

    // clean it up

    theText = theText.replace(/[^0-9a-z]/gi, ‘ ‘).trim().replace(” “,”-“).replace(/-{2,}/g, ‘-‘);

    return theText.toLowerCase();
    }

    function isMobile(){
    //console.log(FLBuilderLayoutConfig.breakpoints.small + jQuery(window).width());
    var browserWidth = FLBuilderLayoutConfig.breakpoints.small + jQuery(window).width();
    if(browserWidth < 991){
    return true;
    }else{
    return false;
    }
    //return (FLBuilderLayoutConfig.breakpoints.small + jQuery(window).width());
    }

    function megaDebug(){
    jQuery(menuElement).each(function(){
    console.log("mega-"+menuTitle(jQuery(this).text()));
    });
    }

Leave a Comment





Level up your Beaver Builder skills

Join 3,264 Beaver Builders and get our monthly-ish dish

We've got a million ideas that we've implemented on over 300+ BB enabled websites. Pop in your email below, and we'll let you know when a new post or plugin is available :)

Newsletter

"*" indicates required fields

This field is for validation purposes and should be left unchanged.

Spam sucks.