In Wordpress Using Elegant Theme's Divi Theme, Long menus don't show

2.9k views Asked by At

The reason I am posting this question is because there is a fundamental issue with the menu system in the Divi theme by Elegant themes for Wordpress.

If you are using this theme, and you have a large menu, you may be running into issues. There are 2 issues to discuss here.

  1. If any menu or sub menu has enough items that it goes past the bottom of the screen, the user cannot see all the items, nor can the user scroll to see the items. (see 1st screenshot below)
  2. If any menu or sub menu goes off the right side of the screen, it get's cut off (or the user never sees it at all), and the user can't scroll to see the menu items (see 2nd screenshot below)

I've looked at the support portal for Elegant Themes and this is a known issue. When users run into it, Elegant Themes support seems to just suggest re-doing the menu so that it does not have so many items or the items do not go off the edge of the screen, or they give a css fix that doesn't work in all situations.

To me those solutions are not a fix, so, I came up with my own fix that works in all situations that I've tested it in. Suggestions are welcome and if someone else has a better fix, please post it.

(Screenshot 1)

Menu goes below the bottom of the screen

(Screenshot 2)

enter image description here

1

There are 1 answers

0
Ray Perea On BEST ANSWER

The fix requires some javascript.

You can either add the javascript to a child theme using the wp_enqueue_scripts hook, or you can add the javascript directly to your theme options in the ePanel. (To add it to the ePanel, go to your ePanel and click on "Integration", and add the following code to the the head of your blog.

The following code is heavily commented so that you coders out there can easily follow what's going on and how it works. If you find any issues with it, please let me know.

<script type="text/javascript">

// Once the document is ready, execute this code
jQuery(document).ready(function(e) {
    'use strict';

    // Set the jQ var to jQuery.
    // You could also use $, but I use jQ... just my preference.
    var jQ = jQuery;

    // Execute the function that fixes the menus
    fixDiviMenus();

    // And whenever the window is resized, re-apply the fixes.
    jQ(window).resize(function() { fixDiviMenus(); });

});

// This variable simply holds a timeout integer.
// It is used so that we don't continually apply the fixes
// over and over as the window is being resized.
var ClFixTimeout;

// This function sets a timeout that fixes the menus
// We set a timeout so that we don't continually apply the fixes
// over and over as the window is being resized.
function fixDiviMenus() {
    "use strict";

    // If the timeout has already been created, clear it
    if (ClFixTimeout) { clearTimeout(ClFixTimeout); }

    // Wait half a second before applying the fixes
    ClFixTimeout = setTimeout(function() { applyDiviMenuFix(); }, 500);
}

// This function actually applies the fixes
function applyDiviMenuFix() {
    'use strict';

    var jQ = jQuery;

    // Get some variables that we use to determine
    // if our menus need fixing
    var windowElem = jQ(window);
    var windowHeight = windowElem.height();
    var windowWidth = windowElem.width();
    var scrollTop = windowElem.scrollTop();

    // If the screen is 980px or less,
    // then the mobile menu is shown. No reconfiguration necessary
    if (windowWidth < 981) { return; }

    // Get all the sub menus
    var subMenus = jQ('ul.sub-menu');

    // Reset the css properties on each sub menu
    // so that we can apply them again if need be.
    subMenus.each(function() {
        var menu = jQ(this);
        menu.css({
            'max-height': '',
            'overflow-y': '',
            'overflow-x': '',
            'margin-left': ''
        });
    });

    // Iterate each sub menu and apply fixes
    subMenus.each(function() {

        var menu = jQ(this);

        // Check to see if this is a mega menu.
        var isMegaMenu = menu.closest('.mega-menu').length > 0;

        // Only the direct sub menu should be considered.
        // All other children of mega menu do not need mods.
        if (isMegaMenu && (!menu.parent().hasClass('mega-menu'))) { return; }

        // Get some values that determine whether our menu
        // will go below the bottom of the screen
        var offset = menu.offset();
        var top = offset.top - scrollTop;
        var height = menu[0].offsetHeight;

        // Set the padding between the bottom of the menu 
        // and the bottom of the page
        // You can adjust this so that your menus go further
        // down or not
        var bottomPadding = 80;

        // Set the maximum height of the menu
        var maxHeight = windowHeight - top - bottomPadding;

        // If it's a mega menu or the menu stretches beyond
        // the bottom of the screen, set max height and overflow
        if (isMegaMenu || height > maxHeight) {
            menu.css({
                'max-height': maxHeight.toString() + 'px',
                'overflow-y': 'auto',
                'overflow-x': 'hidden'
            });
        }

        // If this is a mega menu, we don't need to check if it
        // goes off the right side of the screen
        if (isMegaMenu) { return; }

        // Check for a menu that goes off the right edge of the screen
        var left = offset.left;
        var width = menu[0].offsetWidth;
        var parentMenu = menu.parent().closest('ul');
        var maxLeft = windowWidth - width - 10;

        // If it goes off the edge
        if (left > maxLeft) {

            var marginLeft;

            // If this is a root drop down, simply shift
            // it to the left the correct number of pixels
            if (parentMenu.hasClass('nav')) {
                marginLeft = ( left - maxLeft ) * -1;
            }

            // Otherwise, this is a sub menu, we need to move
            // it to the other side of the parent menu
            else {
                marginLeft = width * 2 * -1;
            }

            // Apply the css to the menu
            menu.css({
                'margin-left': marginLeft.toString() + 'px'
            });

        }
    });
}
</script>