Skip to content

Instantly share code, notes, and snippets.

@Garconis
Last active April 3, 2023 10:02
Show Gist options
  • Star 19 You must be signed in to star a gist
  • Fork 13 You must be signed in to fork a gist
  • Save Garconis/a3855dbd7bfb7eeaebe1601d11b33979 to your computer and use it in GitHub Desktop.
Save Garconis/a3855dbd7bfb7eeaebe1601d11b33979 to your computer and use it in GitHub Desktop.
Divi | WordPress Theme | Mobile Menu Collapsible Submenus via Toggles | CSS & jQuery Tweaks in action: https://i.gyazo.com/93557e9ef5d4aad260e22c6d5896de3b.mp4
/* -- HEADER -- */
/* remove pointer event from menu module mobile wrapper */
.et_pb_module.et_pb_menu .et_mobile_nav_menu {
pointer-events: none;
}
/* make menu module hamburger icon and menu links interactive again */
.et_pb_module.et_pb_menu .et_mobile_nav_menu .mobile_menu_bar,
.et_pb_module.et_pb_menu .et_mobile_nav_menu .et_mobile_menu li a {
pointer-events: auto;
}
/* when mobile menu is open, change hamburger icon to x icon */
#et_mobile_nav_menu .mobile_nav.opened .mobile_menu_bar::before,
.et_pb_module.et_pb_menu .et_mobile_nav_menu .mobile_nav.opened .mobile_menu_bar::before {
content: '\4d';
}
/* make desktop sub sub menu icon be right arrow instead of down arrow */
#top-menu .menu-item-has-children .menu-item-has-children > a:first-child::after,
#et-secondary-nav .menu-item-has-children .menu-item-has-children > a:first-child::after,
.et_pb_module.et_pb_menu .et-menu .menu-item-has-children .menu-item-has-children > a:first-child::after {
content: '5';
}
/* if mobile parent link of child menu is a deadlink, then make it not clickable */
#main-header #mobile_menu.et_mobile_menu .menu-item-has-children > a[href="#0"],
.et_pb_module.et_pb_menu .et_mobile_menu .menu-item-has-children > a[href="#0"] {
pointer-events: none;
}
/* - mobile menu toggling elements, injected via jQuery - */
/* make menu list item be relative, to be able to position toggle within this item */
#main-header #mobile_menu.et_mobile_menu .menu-item-has-children,
.et_pb_module.et_pb_menu .et_mobile_menu .menu-item-has-children {
position: relative;
}
/* the new toggle element, which is added via jQuery */
#main-header #mobile_menu.et_mobile_menu .sub-menu-toggle,
.et_pb_module.et_pb_menu .et_mobile_menu .sub-menu-toggle {
position: absolute;
background-color: rgba(0,0,0,0.03);
z-index: 1;
width: 36px;
height: 36px;
line-height: 36px;
border-radius: 50%;
top: 4px;
right: 4px;
cursor: pointer;
text-align: center;
pointer-events: auto;
}
/* the new toggle element when popped */
#main-header #mobile_menu.et_mobile_menu .sub-menu-toggle.popped,
.et_pb_module.et_pb_menu .et_mobile_menu .sub-menu-toggle.popped {
background-color: rgba(0,0,0,0.1);
}
/* toggle icon */
#main-header #mobile_menu.et_mobile_menu .sub-menu-toggle::before,
.et_pb_module.et_pb_menu .et_mobile_menu .sub-menu-toggle::before {
font-family: "ETmodules" !important;
font-weight: normal;
font-style: normal;
font-variant: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
line-height: 36px;
font-size: 24px;
text-transform: none;
speak: none;
content: '\33';
}
/* toggle icon when triggered */
#main-header #mobile_menu.et_mobile_menu .sub-menu-toggle.popped::before,
.et_pb_module.et_pb_menu .et_mobile_menu .sub-menu-toggle.popped::before {
content: '\32';
}
/* hide sub menus by default */
#main-header #mobile_menu.et_mobile_menu .sub-menu-toggle ~ ul.sub-menu,
.et_pb_module.et_pb_menu .et_mobile_menu .sub-menu-toggle ~ ul.sub-menu {
display: none !important;
padding-left: 0;
}
/* show sub menu when triggered via jQuery toggle, and add slight bg color */
#main-header #mobile_menu.et_mobile_menu .sub-menu-toggle.popped ~ ul.sub-menu,
.et_pb_module.et_pb_menu .et_mobile_menu .sub-menu-toggle.popped ~ ul.sub-menu {
display: block !important;
background-color: rgba(0,0,0,0.03) !important;
}
/* remove sub menu list item left padding, since padding will be on anchors */
#main-header #mobile_menu.et_mobile_menu li li,
.et_pb_module.et_pb_menu .et_mobile_menu li li {
padding-left: 0;
}
/* adjust mobile menu anchors side paddings */
#main-header #mobile_menu.et_mobile_menu li a,
.et_pb_module.et_pb_menu .et_mobile_menu li a {
padding-left: 20px;
padding-right: 20px;
}
/* indent sub menu */
#main-header #mobile_menu.et_mobile_menu li li a,
.et_pb_module.et_pb_menu .et_mobile_menu li li a {
padding-left: 40px;
padding-right: 20px;
}
/* indent sub sub menus further */
#main-header #mobile_menu.et_mobile_menu li li li a,
.et_pb_module.et_pb_menu .et_mobile_menu li li li a {
padding-left: 60px;
padding-right: 20px;
}
/* if mobile menu anchor has toggle, make room for it to fit next to the link */
#main-header #mobile_menu.et_mobile_menu .menu-item-has-children .sub-menu-toggle + a,
.et_pb_module.et_pb_menu .et_mobile_menu .menu-item-has-children .sub-menu-toggle + a {
padding-right: 44px;
}
/* - end mobile menu toggling elements - */
/* undo Divi's default styling of mobile menu links that have children */
#main-header #mobile_menu.et_mobile_menu .menu-item-has-children > a,
.et_pb_module.et_pb_menu .et_mobile_menu .menu-item-has-children > a {
background-color: transparent;
font-weight: inherit;
}
/* make the current page's mobile menu link be different */
#main-header #mobile_menu.et_mobile_menu li.current-menu-item > a,
.et_pb_module.et_pb_menu .et_mobile_menu li.current-menu-item > a {
font-weight: bolder;
}
/* -- END HEADER -- */
jQuery( document ).ready( function( $ ) {
// Create collapsible sub menus in mobile Divi Header Nav
$( '<div class="sub-menu-toggle"></div>' ).insertBefore( '#main-header #mobile_menu.et_mobile_menu .menu-item-has-children > a' );
// Create collapsible sub menus in mobile Divi Theme Builder Menu
$( '<div class="sub-menu-toggle"></div>' ).insertBefore( '.et_pb_module.et_pb_menu .et_mobile_menu .menu-item-has-children > a' );
// Toggle the class to be popped on mobile Divi Header Nav
$( '#main-header #mobile_menu.et_mobile_menu .sub-menu-toggle' ).click(function () {
$(this).toggleClass('popped');
});
// Toggle the class to be popped on mobile Divi Theme Builder Menu
$( '.et_pb_module.et_pb_menu .et_mobile_menu .sub-menu-toggle' ).click(function () {
$(this).toggleClass('popped');
});
// Replace the mobile Divi Theme Builder Menu toggle with different href other than # hash, to prevent scroll to top on sub-menu-toggle clicks
$( '.et_pb_module.et_pb_menu a.mobile_nav[href="#"]' ).attr( 'href', '#0' )
} );
@jason-hub
Copy link

Neither this solution nor https://intercom.help/elegantthemes/en/articles/3725736-how-to-create-a-collapsable-mobile-menu-while-keeping-the-parent-links-active works in the latest version of Chrome for Mac. The +/x icons either make the entire menu collapse when clicked or they don't appear at all.

@gonperes
Copy link

gonperes commented Oct 10, 2022

For the Javascript to work you have to enclose it inside $(document).ready(function () { /* all calls here */ });, because the "ul.et_mobile_menu" element is only appended to the page (by JavaScript/jQuery) after it loads (if you use the Chrome to view the page source you don't see any "ul.et_mobile_menu" element). You could also use setTimeout.

I also removed the "et_pb_menu" class reference from the CSS and JavaScript, because the Divi Theme Builder doesn't use it.

jQuery( document ).ready( function( $ ) {
	
	$(document).ready(function () {
		// Create collapsible sub menus in mobile Divi Header Nav
		$( '<div class="sub-menu-toggle"></div>' ).insertBefore( '#main-header #mobile_menu.et_mobile_menu .menu-item-has-children > a' );
		// Create collapsible sub menus in mobile Divi Theme Builder Menu
		$( '<div class="sub-menu-toggle"></div>' ).insertBefore( '.et_pb_module .et_mobile_menu .menu-item-has-children > a' );


		// Toggle the class to be popped on mobile Divi Header Nav
		$( '#main-header #mobile_menu.et_mobile_menu .sub-menu-toggle' ).click(function () {
			$(this).toggleClass('popped');
		});
		// Toggle the class to be popped on mobile Divi Theme Builder Menu
		$( '.et_pb_module .et_mobile_menu .sub-menu-toggle' ).click(function () {
			$(this).toggleClass('popped');
		});
		// Replace the mobile Divi Theme Builder Menu toggle with different href other than # hash, to prevent scroll to top on sub-menu-toggle clicks
		$( '.et_pb_module a.mobile_nav[href="#"]' ).attr( 'href', '#0' );
	});
} );

@heldopsokken
Copy link

Thanks for sharing your code @Garconis. I fully agree, this should be standard in a payed theme nowadays, I fail to understand why they didnt build this in right away. Anyways youve got us covered. Thanks!

@gonperes
Copy link

gonperes commented Apr 3, 2023

I also removed this CSS code. It was not allowing the menu to scroll if it was too tall and the header was fixed:

/* remove pointer event from menu module mobile wrapper */
.et_pb_module.et_pb_menu .et_mobile_nav_menu {
	pointer-events: none;
}

/* make menu module hamburger icon and menu links interactive again */
.et_pb_module.et_pb_menu .et_mobile_nav_menu .mobile_menu_bar,
.et_pb_module.et_pb_menu .et_mobile_nav_menu .et_mobile_menu li a {
	pointer-events: auto;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment