New mobile menu styles for standard Divi header

21 Jun 2018

Hi everyone,

Here is a second tutorial on customizing the Divi mobile menu.

I have already explained how to improve the appearance of the drop-down menu by removing its margins and changing the appearance of the text.

Today we will go further by completely redefining the way the mobile menu is displayed when you press the associated icon (the infamous hamburger). We will see how to modify height, width and animation independently, which will allow you to create your own style, for example:

  • slide in or expand under the header, on the side or fullwidth,
  • slide in on the side at full height,
  • full screen with animation of your choice.

Prerequisites: Configuring the Divi menu

This tutorial only applies to Divi’s default menu style (to be defined in the theme customization), i.e. logo on the left side and menu on the right.

I will try to adapt the following CSS code for centered and inline centered menus in a future episode.

You can now continue reading the explanations, or skip directly to the mobile menu copy/paste samples, which you will add to the Divi’s custom CSS or your child theme style sheet.

Introduction to the Divi mobile menu

Even if a simple copy/paste will allow you to modify your mobile menu without understanding how, here is a short introduction to its source code for curious and developers.

The Divi mobile menu mainly consists of two elements:

  • the header, defined by .logo_container and #et-top-navigation divs, included in #main-header div;
  • the drop-down menu, defined by the ul#mobile_menu list, encapsulated in the .mobile_nav div, itself encapsulated in #et-top-navigation.

However, the code structure is a bit more complex because there are a lot of cases to manage depending on the theme settings and the screen width (with the desktop menu).

But what interests us today can be summarized in the following HTML skeleton:

<header id="main-header">
	<div class="container clearfix et_menu_container">
		<div class="logo_container"></div>
		<div id="et-top-navigation">
			<div id="et_mobile_nav_menu">
				<div class="mobile_nav opened">
					<span class="mobile_menu_bar mobile_menu_bar_toggle"></span>
					<ul id="mobile_menu" class="et_mobile_menu"></ul>
				</div>
			</div>
		</div> <!-- #et-top-navigation -->
	</div> <!-- .container -->
</header>

In order to modify width, height and animation of the drop-down menu, we will mainly edit the ul#mobile_menu list, but we will still have to modify some additional elements to make everything work correctly.

Close icon

The strict minimum (Come on, ET…), let’s replace the hamburger by a cross when menu is open:

@media only screen and (max-width: 980px) {

	.mobile_nav.opened .mobile_menu_bar:before {
		content: "\4d";
	}

}

Removing margins

The right and left margins of the Divi mobile menu must be deleted. On the one hand to preserve your eyes, and on the other hand to be able to display the menu properly in full screen or full width, and get clean transitions.

The main container must therefore be enlarged and the position of the logo and hamburger icon adapted:

@media only screen and (max-width: 980px) {

	#main-header .container.clearfix.et_menu_container {
		width: 100%;
	}
	.logo_container {
		padding-left: 30px;
	}
	#et-top-navigation {
		padding-right: 30px;
	}

}

Menu positioning

The menu can be displayed under the header, or start at the top of the screen (full height or full screen). In the second case, we remove the color top border that would otherwise be stuck at the top of the screen, and we add a vertical padding to leave room for the logo and the close icon. We also have to set the logo and close icon z-indexes ABOVE the drop-down menu to still have access to it.

A horizontal slide-in menu can come from the right or left, so we will stick it on one side or the other, and we will set the opposite side to auto since the width of the menu can be variable.

@media only screen and (max-width: 980px) {

	#mobile_menu {
		display: block !important;

		/* Right slide-in */
		right: 0;
		left: auto;
		/* Left slide-in */
		right: auto;
		left: 0;
		/* Expand */
		right: 0;
		left: 0;
		
		/* Under the header */
		top: 80px;
		/* Full screen or full height */
		top: 0;
		padding-top: 80px;
		border-top: none;
	}

	/* Full height */
	.mobile_menu_bar, #logo {
		z-index: 10000;
	}

}

Menu width

The menu width is 100% by default, but you can simply change it with:

@media only screen and (max-width: 980px) {

	#mobile_menu {
		width: 400px;
	}

}

Note that you can use a media query if necessary to limit the width of the menu beyond a certain screen width, but keep it at 100% below to avoid a too tight display:

@media only screen and (max-width: 480px) {

	#mobile_menu {
		width: 100%;
	}

}

Menu height

The menu height adapts by default to the length of the list containing the menu items, which suits us very well.

But we can order the menu to occupy the full height (full screen menu or slide in menu with full height):

@media only screen and (max-width: 980px) {

	#mobile_menu {
		min-height: 100vh;
	}

}

or only the height available under the header:

@media only screen and (max-width: 980px) {

	#mobile_menu {
		min-height: calc( 100vh - 80px );
	}

}

Menu animation

The most difficult part in displaying the menu is the CSS animation which makes the menu list appear.

It should be known for example that if setting the opacity to 0 allows to hide the drop-down menu, it does not physically remove the list, and all the menu links are still clickable! Even by modifying the z-index property, I couldn’t avoid it. Please let me know if you have a trick…

Or, on iOS system, the “overflow: hidden” behaviour on the body and html elements is a bit strange, and a horizontal scrollbar appears when you want to “push” the menu off the screen in the case of a slide in menu.

Thus, to get around these two problems, the only simple and global solution I could find (on the internet, I confess) is to use a 3D rotation of the list to position it perpendicularly to the screen plane! Then, it is physically not displayed on the screen (width is 0) and does not need to be taken off the screen.

For example, for the animation I call expand, I rotate around the vertical axis passing through the center of the menu, which gives the impression that it extends from the center to the edges.

For slide in, the rotation is done around the vertical axis passing through an edge (right or left), which simulates a lateral displacement.

To unroll from the top, we would use the horizontal axis passing through the upper edge, etc…

I will not detail here each possible animation, but you will find a few of them in the examples below. You will notice that I reduced the transition time to 200ms because for me the default menu appearance is really too slow.

Menu colors

By default, the dropdown menu uses the same colors as the header, thus, those defined for the primary bar in the theme customization.

You can change them with:

@media only screen and (max-width: 980px) {

	#mobile_menu {
		background-color: #fff !important;
	}
	#mobile_menu li a {
		color: #333;
	}

}

Example 1 : Full width expand mobile menu that opens under the header

CSS code to add to your stylesheet (for example your child theme’s style.css file) or to Divi’s custom CSS.

/* Full width expand mobile menu that opens under the header */
@media only screen and (max-width: 980px) {

	.mobile_nav.opened .mobile_menu_bar:before {
		content: "\4d";
	}
	#main-header .container.clearfix.et_menu_container {
		width: 100%;
	}
	.logo_container {
		padding-left: 30px;
	}
	#et-top-navigation {
		padding-right: 30px;
	}
	#mobile_menu {
		display: block !important;
		right: 0;
		left: 0;
		top: 80px;
		min-height: calc( 100vh - 80px );
		transition: all .2s ease-in-out;
		transform-origin: center;
	}
	.mobile_nav.closed #mobile_menu {
		transform: rotateY(90deg);
		opacity: 0;
	}
	.mobile_nav.opened #mobile_menu {
		transform: rotateY(0);
		opacity: 1;
	}

}

Exemple 2 : Full height slide-in menu that comes from the right

CSS code to add to your stylesheet (for example your child theme’s style.css file) or to Divi’s custom CSS.

/* Full height slide-in menu that comes from the right */
@media only screen and (max-width: 980px) {

	.mobile_nav.opened .mobile_menu_bar:before {
		content: "\4d";
	}
	#main-header .container.clearfix.et_menu_container {
		width: 100%;
	}
	.logo_container {
		padding-left: 30px;
	}
	#et-top-navigation {
		padding-right: 30px;
	}
	.mobile_menu_bar, #logo {
		z-index: 10000;
	}
	#mobile_menu {
		display: block !important;
		right: 0;
		left: auto;
		top: 0;
		padding-top: 80px;
		min-height: 100vh;
		width: 400px;
		border-top: none;
		transition: all .2s ease-in-out;
		transform-origin: right;
	}
	.mobile_nav.closed #mobile_menu {
		transform: rotateY(90deg);
		opacity: 0;
	}
	.mobile_nav.opened #mobile_menu {
		transform: rotateY(0);
		opacity: 1;
	}

}

@media only screen and (max-width: 480px) {

	#mobile_menu {
		width: 100%;
	}

}

Exemple 3 : Full screen slide-in menu coming from below

CSS code to add to your stylesheet (for example your child theme’s style.css file) or to Divi’s custom CSS.

/* Full screen slide-in menu coming from below */
@media only screen and (max-width: 980px) {

	.mobile_nav.opened .mobile_menu_bar:before {
		content: "\4d";
	}
	#main-header .container.clearfix.et_menu_container {
		width: 100%;
	}
	.logo_container {
		padding-left: 30px;
	}
	#et-top-navigation {
		padding-right: 30px;
	}
	.mobile_menu_bar, #logo {
		z-index: 10000;
	}
	#mobile_menu {
		display: block !important;
		right: 0;
		left: 0;
		top: 0;
		padding-top: 80px;
		min-height: 100vh;
		border-top: none;
		transition: all .2s ease-in-out;
		transform-origin: bottom;
	}
	.mobile_nav.closed #mobile_menu {
		transform: rotateX(90deg);
		opacity: 0;
	}
	.mobile_nav.opened #mobile_menu {
		transform: rotateX(0);
		opacity: 1;
	}

}

Conclusion

In the Divi source code, the mobile menu is animated using java: the CSS used for the display is dynamically modified. Fortunately, we were able to directly change this behavior in CSS.

However, once in a while, if you click too fast, for example, when the menu appears, there may be a vertical movement of the menu, or a slight delay in its appearance. I think that depending on the length of the chosen animation and the moment you click, the CSS transition conflicts with Divi’s java code which runs in parallel.

So for a perfect animation in 100% of the cases, you would have to modify Divi to disable this code. If someone has a clean and simple idea…

From these few samples, I hope you will be able to innovate and create always better mobile menus!