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.
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)
(Screenshot 2)
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>