Create Better Divi Headers

Create The Smooth Submenus Effect For Divi Desktop Menu

by | Aug 19, 2022 | 2 comments

In this tutorial we’ll be creating the smooth submenus hover effect for Divi desktop menu submenus.

This effect keeps the submenu always visible while you move the cursor over the parent menu items.

The submenu is moving smoothly from one parent menu item to another adjusting it’s size according to the currently visible submenu’s dimensions.

You can see a similar effect on websites like Stripe.com or Elegantthemes.com, these websites use this effect for megamenus but we’ll apply it to the classic submenus.

We’ll implement this effect for the Divi theme default header desktop menu as well as the menus created using the Menu and Fullwidth Menu modules and the Divi MadMenu extension.

Contents

How It Works

The implementation of the smooth submenus effect is rather simple.

Basically, we’ll create an HTML element that will be used as the background for all submenus, and we’ll insert it into the menu container.

Then, as the mouse moves over the parent menu items of our menu this submenu background element will be smoothly repositioned under the corresponding parent menu item, and resized to match the dimensions of the submenu of this menu item.

This creates an illusion that multiple submenus are smoothly transitioning one into another, whereas it’s actually the same element used as the background for all submenus with transparent backgrounds.

To implement this effect we’ll use custom CSS and JavaScript.

You can follow the tutorial and try to implement the effect by yourself.

Or you can download the demo header template with this effect already enabled for and use it on your website(s).

The Smooth Submenus Effect JS Part

The JavaScript code that we’ll use consists of a few functions that will help us create the submenu background element and make it work the way we need when the mouse enters/leaves the parent menu items.

Creating the Submenu Background and Arrow Elements

Let’s start with creating the submenu background element and injecting it into the menu so that we can manipulate it’s positioning and dimensions.

To create it we will use the createSubmenuBg() JS function:

/**
 * Create the submenu background element
 * and insert it into the menu <nav> element before <ul> element.
 * 
 * @param {HTMLelement}    nav     Menu <nav> element.
 * @param {HTMLelement}    ul      Menu <ul> element.
 */
function createSubmenuBg(nav, ul){
    // create submenu background element
    let submenuBgWrapper = document.createElement("div"),
        submenuBg = document.createElement("div"),
        arrow     = document.createElement("span");
    
    // add CSS classes
    submenuBgWrapper.classList.add("dvcs_submenu_bg_wrapper");
    submenuBg.classList.add("dvcs_submenu_bg");
    arrow.classList.add("dvcs_arrow");

    // insert into menu
    nav.insertBefore(submenuBgWrapper, ul);
    submenuBgWrapper.appendChild(submenuBg);
    submenuBg.appendChild(arrow);
}
This function creates the submenu background element (including the arrow) and inserts it into the menu <nav> element before <ul> element. We’ll be styling it later in the tutorial.

Showing and Hiding the Submenu Background

Next we need to show/hide the submenu background on mouse enter and mouse leave events.

We need to show the submenu background when the mouse enters(hovers over) the parent menu item, and hide it when it leaves.

To show it we’ll use the handleEnter() JS function:

/**
 * Handle the submenu bakcground on menu item mouse enter.
 * 
 * Shows the submenu background when the parent menu item is hovered over
 * and updates it's coordinates and size values accordingly.
 * 
 * @param {HTMLelement} item                The menu item that is currently hovered over.
 * @param {HTMLelement} nav                 Menu <nav> element.
 * @param {HTMLelement} submenuBgWrapper    Submenu background wrapper.
 * @param {HTMLelement} submenuBg           Submenu background.
 */
function handleEnter(item, nav, submenuBgWrapper, submenuBg){

    // coordinates of the current submenu and menu <nav> element
    const submenu       = item.querySelector('.sub-menu'),
          submenuRect   = submenu.getBoundingClientRect(),
          navRect       = nav.getBoundingClientRect();

    // submenu background values
    const bg = {
        height: submenuRect.height,
        width: submenuRect.width,
        top: submenuRect.top - navRect.top,
        left: submenuRect.left - navRect.left
    };

    // add CSS classes
    item.classList.add('dvcs-item-enter');
    setTimeout(() => item.classList.contains('dvcs-item-enter') && item.classList.add('dvcs-item-enter-active'), 150);
    submenuBg.classList.add('dvcs_open');

    // set the submenu wrapper background properties
    submenuBgWrapper.style.setProperty('transform', `translate(${bg.left}px, ${bg.top}px)`);
    submenuBgWrapper.style.setProperty('width', `${bg.width}px`);
    submenuBgWrapper.style.setProperty('height', `${bg.height}px`);

    // set the submenu background properties
    submenuBg.style.setProperty('width', `${bg.width}px`);
    submenuBg.style.setProperty('height', `${bg.height}px`);
}
The handleEnter() function shows the submenu background when the parent menu item is hovered over, and updates it’s coordinates and size values accordingly depending on the parent menu item’s coordinates and it’s submenu’s dimensions (width and height values).

We also need to hide the submenu background and reset it’s size values when the mouse leaves the parent menu item.

To handle that we’ll use the handleLeave() function:

/**
 * Handle the submenu background hiding.
 * 
 * Hides the submenu background when the mouse leaves
 * the parent menu item.
 * 
 * @param {HTMLelement} item        The menu item.
 * @param {HTMLelement} submenuBg   Submenu background.
 */
function handleLeave(item, submenuBg){

    // remove CSS classes
    item.classList.remove('dvcs-item-enter', 'dvcs-item-enter-active');
    submenuBg.classList.remove('dvcs_open');

    // remove the submenu background properties
    submenuBg.style.setProperty('width', '');
    submenuBg.style.setProperty('height', '');
}

We also need to detect when the mouse enters and leaves the menu <ul> element to enable/disable the submenu background transition as well as reset it’s size values (width and height).

To do that we’ll use the handleEnterUl() and the handleLeaveUl() functions for the <ul> element mouse enter and mouse leave events respectively:

    /**
     * Handle the submenu background when mouse enters the menu <ul> element.
     * 
     * Enables transition for the submenu background to ensure it
     * moves smoothly in between the adjacent parent menu items. 
     * 
     * @param {HTMLelement} submenuBgWrapper Submenu background wrapper.
     */
    function handleEnterUl(submenuBgWrapper){		
        setTimeout(function(){submenuBgWrapper.classList.add('dvcs-animatable')}, 150);
    }
    
    /**
     * Handle the submenu background when mouse leaves the menu <ul> element.
     * 
     * Disables transition for the submenu background and 
     * resets it's size.
     * 
     * @param {HTMLelement} submenuBgWrapper    Submenu background wrapper.
     * @param {HTMLelement} submenuBg           Submenu background. 
     */
    function handleLeaveUl(submenuBgWrapper, submenuBg){
        submenuBgWrapper.classList.remove('dvcs-animatable');
    
        // remove the submenu background properties
        submenuBg.style.setProperty('width', '');
        submenuBg.style.setProperty('height', '');
    }

      Finally, we need to make all of the functions mentioned above work together nicely in order for the smooth submenus effect to work as expected.

      And to do that we will use the effect() function:

        /**
         * Handle the "smooth submenus" effect.
         * 
         * @param {string} menuSelector     Menu selector, CSS ID or class. Default: '#et-top-navigation'
         * @param {string} navSelector      Menu <nav> element selector, CSS ID or class. Default: '#top-menu-nav'
         * @param {string} ulSelector       Menu <ul> element selector, CSS ID or class. Default: '#top-menu'
         */
        function effect(menuSelector = '#et-top-navigation', navSelector = '#top-menu-nav', ulSelector = '#top-menu'){
        
            // select the menu
            let menu = document.querySelector(menuSelector);
        
            if(!menu){return}
        
            // select the menu <nav> and <ul> elements
            let nav  = menu.querySelector(navSelector),
                ul   = nav.querySelector(ulSelector);
        
            // insert the submenu background element(with arrow) into the <nav> element
            createSubmenuBg(nav, ul);
        
            const items = nav.querySelectorAll(`${ulSelector} > li.menu-item-has-children`),
                  submenuBgWrapper = nav.querySelector('.dvcs_submenu_bg_wrapper'),
                  submenuBg = nav.querySelector('.dvcs_submenu_bg');
        
            // handle <ul> element mouse enter
            ul.addEventListener('mouseenter', () => handleEnterUl(submenuBgWrapper));
        
            // handle menu items mouse enter
            items.forEach(item => item.addEventListener('mouseenter', () => handleEnter(item, nav, submenuBgWrapper, submenuBg)));
        
            // handle menu items mouse leave
            items.forEach(item => item.addEventListener('mouseleave', () => handleLeave(item, submenuBg)));
        
            // handle <ul> element mouse leave
            ul.addEventListener('mouseleave', () => handleLeaveUl(submenuBgWrapper, submenuBg));
        }

          All JS Code Combined

            Let’s bring all our JavaScript functions together in an object (let’s name it dvcsSmoothSubmenus{}) and add this object to the window object.

              window.dvcsSmoothSubmenus = {
                  /**
                   * Create the submenu background element
                   * and insert it into the menu <nav> element before <ul> element.
                   * 
                   * @param {HTMLelement}    nav     Menu <nav> element.
                   * @param {HTMLelement}    ul      Menu <ul> element.
                   */
                   createSubmenuBg: function(nav, ul){
                      // create submenu background element
                      let submenuBgWrapper = document.createElement("div"),
                          submenuBg = document.createElement("div"),
                          arrow     = document.createElement("span");
                      
                      // add CSS classes
                      submenuBgWrapper.classList.add("dvcs_submenu_bg_wrapper");
                      submenuBg.classList.add("dvcs_submenu_bg");
                      arrow.classList.add("dvcs_arrow");
              
                      // insert into menu
                      nav.insertBefore(submenuBgWrapper, ul);
                      submenuBgWrapper.appendChild(submenuBg);
                      submenuBg.appendChild(arrow);
                  },
              
                  /**
                   * Handle the submenu bakcground on menu item mouse enter.
                   * 
                   * Shows the submenu background when the parent menu item is hovered over
                   * and updates it's coordinates and size values accordingly.
                   * 
                   * @param {HTMLelement} item                The menu item that is currently hovered over.
                   * @param {HTMLelement} nav                 Menu <nav> element.
                   * @param {HTMLelement} submenuBgWrapper    Submenu background wrapper.
                   * @param {HTMLelement} submenuBg           Submenu background.
                   */
                  handleEnter: function(item, nav, submenuBgWrapper, submenuBg){
              
                      // coordinates of the current submenu and menu <nav> element
                      const submenu      = item.querySelector('.sub-menu'),
                            submenuRect  = submenu.getBoundingClientRect(),
                            navRect       = nav.getBoundingClientRect();
              
                      // submenu background values
                      const bg = {
                          height: submenuRect.height,
                          width: submenuRect.width,
                          top: submenuRect.top - navRect.top,
                          left: submenuRect.left - navRect.left
                      };
              
                      // add CSS classes
                      item.classList.add('dvcs-item-enter');
                      setTimeout(() => item.classList.contains('dvcs-item-enter') && item.classList.add('dvcs-item-enter-active'), 150);
                      submenuBg.classList.add('dvcs_open');
              
                      // set the submenu wrapper background properties
                      submenuBgWrapper.style.setProperty('transform', `translate(${bg.left}px, ${bg.top}px)`);
                      submenuBgWrapper.style.setProperty('width', `${bg.width}px`);
                      submenuBgWrapper.style.setProperty('height', `${bg.height}px`);
              
                      // set the submenu background properties
                      submenuBg.style.setProperty('width', `${bg.width}px`);
                      submenuBg.style.setProperty('height', `${bg.height}px`);
                  },
              
                  /**
                   * Handle the submenu background hiding.
                   * 
                   * Hides the submenu background when the mouse leaves
                   * the parent menu item.
                   * 
                   * @param {HTMLelement} item        The menu item.
                   * @param {HTMLelement} submenuBg   Submenu background.
                   */
                  handleLeave: function(item, submenuBg){
              
                      // remove CSS classes
                      item.classList.remove('dvcs-item-enter', 'dvcs-item-enter-active');
                      submenuBg.classList.remove('dvcs_open');
              
                      // remove the submenu background properties
                      submenuBg.style.setProperty('width', '');
                      submenuBg.style.setProperty('height', '');
                  },
              
                  /**
                   * Handle the submenu background when mouse enters the menu <ul> element.
                   * 
                   * Enables transition for the submenu background to ensure it
                   * moves smoothly in between the adjacent parent menu items. 
                   * 
                   * @param {HTMLelement} submenuBgWrapper Submenu background wrapper.
                   */
                  handleEnterUl: function(submenuBgWrapper){		
                      setTimeout(function(){submenuBgWrapper.classList.add('dvcs-animatable')}, 150);
                  },
              
                  /**
                   * Handle the submenu background when mouse leaves the menu <ul> element.
                   * 
                   * Disables transition for the submenu background and 
                   * resets it's size.
                   * 
                   * @param {HTMLelement} submenuBgWrapper    Submenu background wrapper.
                   * @param {HTMLelement} submenuBg           Submenu background. 
                   */
                  handleLeaveUl: function(submenuBgWrapper, submenuBg){
                      submenuBgWrapper.classList.remove('dvcs-animatable');
              
                      // remove the submenu background properties
                      submenuBg.style.setProperty('width', '');
                      submenuBg.style.setProperty('height', '');
                  },
              
                  /**
                   * Handle the "smooth submenus" effect.
                   * 
                   * @param {string} menuSelector     Menu selector, CSS ID or class. Default: '#et-top-navigation'
                   * @param {string} navSelector      Menu <nav> element selector, CSS ID or class. Default: '#top-menu-nav'
                   * @param {string} ulSelector       Menu <ul> element selector, CSS ID or class. Default: '#top-menu'
                   */
                  effect: function(menuSelector = '#et-top-navigation', navSelector = '#top-menu-nav', ulSelector = '#top-menu'){
              
                      // select the menu
                      let menu = document.querySelector(menuSelector);
              
                      if(!menu){return}
              
                      // select the menu <nav> and <ul> elements
                      let nav  = menu.querySelector(navSelector),
                          ul   = nav.querySelector(ulSelector);
              
                      // insert the submenu background element(with arrow) into the <nav> element
                      this.createSubmenuBg(nav, ul);
              
                      const items = nav.querySelectorAll(`${ulSelector} > li.menu-item-has-children`),
                            submenuBgWrapper = nav.querySelector('.dvcs_submenu_bg_wrapper'),
                            submenuBg = nav.querySelector('.dvcs_submenu_bg');
              
                      // handle <ul> element mouse enter
                      ul.addEventListener('mouseenter', () => this.handleEnterUl(submenuBgWrapper));
              
                      // handle menu items mouse enter
                      items.forEach(item => {
                          item.addEventListener('mouseenter', () => {
                              this.handleEnter(item, nav, submenuBgWrapper, submenuBg)
                          })
                      });
              
                      // handle menu items mouse leave
                      items.forEach(item => {
                          item.addEventListener('mouseleave', () => {
                              this.handleLeave(item, submenuBg)
                          })
                      });
              
                      // handle <ul> element mouse leave
                      ul.addEventListener('mouseleave', () => this.handleLeaveUl(submenuBgWrapper, submenuBg));
                  }
              }

                It may seem like a lot of code but don’t be scared, almost half of it is just comments :)

                Now we can call the effect() function like this: dvcsSmoothSubmenus.effect(), and pass the necessary arguments to it depending on the menu we are applying this effect to.

                Next, let’s move on to the CSS for the smooth submenus effect.

                  The Smooth Submenus Effect CSS

                    The menus that we’ll be applying our smooth submenus effect to all have their own default styling with some CSS rules conflicting with the effect.

                    So, we need to fix that by using custom CSS to override those CSS rules.

                    And we also need to add the submenu background and the arrow elements CSS.

                      CSS: Submenu Background and Arrow Elements

                        Let’s apply the CSS for the submenu background and arrow elements that we are creating using createSubmenuBg() function as explained above:

                          /* visible submenu */
                          .dvcs-item-enter > .sub-menu {
                              display: block;
                          }
                          
                          .dvcs-item-enter-active > .sub-menu {
                              opacity: 1;
                          }
                          
                          /* submenu background wrapper */
                          .dvcs_submenu_bg_wrapper {
                              position: absolute;
                              z-index: 1;
                          }
                          
                          .dvcs_submenu_bg_wrapper.dvcs-animatable {
                              transition: transform 0.2s; 
                              transform-origin: 50% 0;
                          }
                          
                          .dvcs_submenu_bg_wrapper:not(.dvcs-animatable) {
                              pointer-events: none;
                          }
                          
                          /* submenu background */
                          .dvcs_submenu_bg {
                              width: 150px;
                              height: 100px;
                              position: absolute;
                              left: 50%;
                              transform: translateX(-50%);
                              background: #fff;
                              border-radius: 4px;
                              box-shadow: 0px 4px 15px 5px rgba(0, 0, 0, 0.05);
                              transition: all 0.3s, opacity 0.1s, transform 0.2s;
                              transform-origin: 50% 0;
                              display: flex;
                              justify-content: center;
                              opacity: 0;
                          }
                          
                          .dvcs_submenu_bg.dvcs_open {
                              opacity: 1;
                          }
                          
                          /* submenu background arrow */
                          .dvcs_arrow {
                              position: absolute;
                              width: 20px;
                              height: 20px;
                              display: block;
                              background: white;
                              transform: translateY(-50%) rotate(45deg);
                              pointer-events: none;
                          }

                            CSS: Divi Theme Default Menu

                              Next let’s add the Divi theme default menu CSS.

                              To get the Divi theme default menu submenus ready for the smooth submenus effect we need to do the followings:

                                  • Make the submenu background transparent
                                  • Align submenus in the middle of the parent menu items
                                  • Remove submenu box-shadow
                                  • Remove the parent menu item arrow
                                  • Remove the default spacing between the menu items
                                  • Adjust the menu item padding values.

                              Here is the CSS:

                                /* Divi theme DEFAULT menu CSS */
                                /* center submenus */
                                #et-top-navigation #top-menu > li > ul {
                                    left: 50%;
                                    transform: translate(-50%, 0) translateZ(0);
                                    background-color: transparent !important;
                                }
                                
                                /* remove submenu box-shadow */
                                #et-top-navigation #top-menu li ul {
                                    box-shadow: none !important;
                                }
                                
                                @media all and (min-width: 981px){
                                    /* remove space between menu items of Divi default menu */
                                    #top-menu {
                                        display: flex;
                                    }
                                }
                                
                                /* remove parent item arrow */
                                #main-header #top-menu > li.menu-item-has-children > a:after {
                                    content: "";
                                }
                                
                                /* parent item link padding */
                                #main-header #top-menu > li > a {
                                    padding-left: 10px;
                                    padding-right: 10px;
                                }
                                
                                /* menu top level items padding */
                                #top-menu > li {
                                    padding: 0px;
                                }
                                /* END Divi theme DEFAULT menu CSS */

                                  CSS: Divi Menu and Fullwidth Menu Modules

                                    Similarly to the Divi default menu, we need to prepare the Menu and Fullwidth Menu module submenus for applying the effect as well.

                                    We need to do the followings:

                                        • Align submenus in the middle of the parent menu items
                                        • Remove submenu box-shadow
                                        • Remove the parent menu item arrow
                                        • Adjust the menu item padding values.

                                    Also we need to assign a CSS class (or ID) to the menu module which will be used both in CSS and as argument for the effect() function as explained below.

                                    I’ve assigned the dvcs_smooth_submenus CSS class (in module settings Advanced -> CSS ID & Classes -> CSS Class) for demonstration, you can use any other CSS class you like but make sure you replace the dvcs_smooth_submenus class everywhere in CSS and JS code.

                                    Since both these menu modules use similar CSS selectors the custom CSS is the same for both:

                                      /* Divi Menu and Fullwidth Menu module CSS */
                                      /* center submenus */
                                      .dvcs_smooth_submenus .et_pb_menu__menu nav .et-menu > li > ul {
                                          left: 50%;
                                          transform: translate(-50%, 0) translateZ(0);
                                          background-color: transparent !important;
                                      }
                                      
                                      /* remove submenu box-shadow */
                                      .dvcs_smooth_submenus .nav li ul {
                                          box-shadow: none !important;
                                      }
                                      
                                      /* remove parent item arrow */
                                      .dvcs_smooth_submenus .et-menu > li.menu-item-has-children > a:after {
                                          content: "";
                                      }
                                      
                                      /* parent item link */
                                      .dvcs_smooth_submenus .et-menu > li > a {
                                          padding-left: 10px;
                                          padding-right: 10px;
                                      }
                                      /* END Divi Menu and Fullwidth Menu module CSS */

                                        CSS: Divi MadMenu Module

                                          The smooth submenus effect is not available in our Divi MadMenu extension (yet) but we can implement it for the Divi MadMenu menus as well using the same JS code and a few lines of custom CSS.

                                          For the menu created using the Divi MadMenu extension all we need to do using custom CSS is to center the submenus and hide the parent menu item arrow button.

                                          And let’s assign the dvcs_madmenu_smooth_submenus custom CSS class in MadMenu Settings -> Advanced -> CSS ID & Classes -> CSS Class.

                                          Here is the CSS:

                                            /* Divi MadMenu extension CSS */
                                            /* center submenus */
                                            .dvcs_madmenu_smooth_submenus .dvmm_menu__menu .dvmm_menu > li > ul {
                                                left: 50%;
                                                transform: translate(-50%, 0) translateZ(0);
                                                background-color: transparent !important;
                                            }
                                            
                                            /* remove parent item arrow */
                                            .dvcs_madmenu_smooth_submenus .dvmm_menu__menu .dvmm_menu > li > a .dvmm_submenu_toggle {
                                                display: none;
                                            }
                                            /* END Divi MadMenu extension CSS */

                                              All CSS Combined

                                                To make the smooth submenus effect work you need to use both the submenu backgroud and arrow CSS and any of the menu specific CSS depending on which menu you want to apply this effect to (Divi default menu, Divi menu modules menus, or Divi MadMenu extension menu).

                                                But we can also combine all of the CSS provided above so that we have it all in one piece.

                                                You might have already noticed that the custom CSS for Divi default menu, menu modules and Divi MadMenu extension menus contain similar CSS rules which we can combine so that we don’t have duplicate rules.

                                                So, here is the final combined CSS:

                                                  /* SMOOTH SUBMENUS EFFECT CSS */
                                                  /* Submenu background and arrow */
                                                  /* visible submenu */
                                                  .dvcs-item-enter > .sub-menu {
                                                      display: block;
                                                  }
                                                  
                                                  .dvcs-item-enter-active > .sub-menu {
                                                      opacity: 1;
                                                  }
                                                  
                                                  /* submenu background wrapper */
                                                  .dvcs_submenu_bg_wrapper {
                                                      position: absolute;
                                                      z-index: 1;
                                                  }
                                                  
                                                  .dvcs_submenu_bg_wrapper.dvcs-animatable {
                                                      transition: transform 0.2s; 
                                                      transform-origin: 50% 0;
                                                  }
                                                  
                                                  .dvcs_submenu_bg_wrapper:not(.dvcs-animatable) {
                                                      pointer-events: none;
                                                  }
                                                  
                                                  /* submenu background */
                                                  .dvcs_submenu_bg {
                                                      width: 150px;
                                                      height: 100px;
                                                      position: absolute;
                                                      left: 50%;
                                                      transform: translateX(-50%);
                                                      background: #fff;
                                                      border-radius: 4px;
                                                      box-shadow: 0px 4px 15px 5px rgba(0, 0, 0, 0.05);
                                                      transition: all 0.3s, opacity 0.1s, transform 0.2s;
                                                      transform-origin: 50% 0;
                                                      display: flex;
                                                      justify-content: center;
                                                      opacity: 0;
                                                  }
                                                  
                                                  .dvcs_submenu_bg.dvcs_open {
                                                      opacity: 1;
                                                  }
                                                  
                                                  /* submenu background arrow */
                                                  .dvcs_arrow {
                                                      position: absolute;
                                                      width: 20px;
                                                      height: 20px;
                                                      display: block;
                                                      background: white;
                                                      transform: translateY(-50%) rotate(45deg);
                                                      pointer-events: none;
                                                  }
                                                  /* END Submenu background and arrow */
                                                  
                                                  /* Menus CSS */
                                                  /* first level submenus */
                                                  .dvcs_madmenu_smooth_submenus .dvmm_menu__menu .dvmm_menu > li > ul,
                                                  .dvcs_smooth_submenus .et_pb_menu__menu nav .et-menu > li > ul,
                                                  #et-top-navigation #top-menu > li > ul {
                                                      left: 50%;
                                                      transform: translate(-50%, 0) translateZ(0);
                                                      background-color: transparent !important;
                                                  }
                                                  
                                                  /* remove submenu box-shadow */
                                                  .dvcs_smooth_submenus .nav li ul,
                                                  #et-top-navigation #top-menu li ul {
                                                      box-shadow: none !important;
                                                  }
                                                  
                                                  @media all and (min-width: 981px){
                                                      /* remove space between menu items (Divi default menu) */
                                                      #top-menu {
                                                          display: flex;
                                                      }
                                                  }
                                                  
                                                  /* remove parent item arrow */
                                                  #main-header #top-menu > li.menu-item-has-children > a:after,
                                                  .dvcs_smooth_submenus .et-menu > li.menu-item-has-children > a:after {
                                                      content: "";
                                                  }
                                                  
                                                  /* parent item link */
                                                  #main-header #top-menu > li > a,
                                                  .dvcs_smooth_submenus .et-menu > li > a {
                                                      padding-left: 10px;
                                                      padding-right: 10px;
                                                  }
                                                  
                                                  /* top level items padding (Divi default menu) */
                                                  #top-menu > li {
                                                      padding: 0px;
                                                  }
                                                  
                                                  /* remove parent item arrow (Divi MadMenu) */
                                                  .dvcs_madmenu_smooth_submenus .dvmm_menu__menu .dvmm_menu > li > a .dvmm_submenu_toggle {
                                                      display: none;
                                                  }
                                                  /* END Menus CSS */
                                                  /* END SMOOTH SUBMENUS EFFECT CSS */

                                                    Implementation

                                                      To implement the smooth submenus effect first you need to add the combined CSS and combined JS to your website.

                                                      You can add them either in Divi -> Theme Options if you want the effect to be enabled sitewide, or using a Code module in the header template so that it works for that specific header only.

                                                      After that call the effect() function with necessary arguments for each menu as demonstrated below.

                                                        Implementation: Divi Theme Default Menu

                                                          To enable the smooth submenus effect for the Divi theme default menu first we need to make sure the submenu animation is set to Fade in Divi -> Theme Customizer -> Header & Navigation -> Primary Menu Bar -> Dropdown Menu Animation field.

                                                          Then call the effect() function:

                                                            document.addEventListener('DOMContentLoaded', function(){
                                                                // Divi theme default menu
                                                                dvcsSmoothSubmenus.effect();
                                                            })

                                                              As you can see we’ve called the effect() function without passing any arguments to it.

                                                              That’s because all parameters of the effect() function have the Divi default menu selectors as their default values (as you can see from the function definition).

                                                              So, if you call the function without passing any arguments to it then the effect will work for the Divi default menu only.

                                                              We can call the effect() function with the Divi default menu arguments as well and it would work just as fine:

                                                                document.addEventListener('DOMContentLoaded', function(){
                                                                    // Divi theme default menu
                                                                    dvcsSmoothSubmenus.effect('#et-top-navigation', '#top-menu-nav', '#top-menu');
                                                                })

                                                                  All three arguments are the selectors of the default menu main container, the <nav> element and the <ul> element from left to right respectively as demonstrated on the diagram below.

                                                                    Implementation: Divi Menu and Fullwidth Menu Modules

                                                                      For the Menu and Fullwidth Menu modules we also need to set the submenu animation to Fade in the menu module settings Design -> Animation -> Dropdown Menu Animation.

                                                                      Since Divi menu modules use similar selectors we can call the effect() function with the same arguments for both.

                                                                      It works the same way as with the Divi default menu except for the 1st argument.

                                                                      The 1st argument should be a custom selector set in the menu module settings Advanced -> CSS ID & Classes fields.

                                                                      (We can use either ID or CSS class selectors for the effect() function arguments.)

                                                                      So, let’s assign the dvcs_smooth_submenus CSS class to the Menu module and use it as the first argument. Make sure you use the same CSS class in the menu modules custom CSS too (as mentioned in the CSS section above).

                                                                      The 2nd and 3rd arguments are same for both menu modules: .et-menu-nav (the <nav> element selector) and .et-menu (the <ul> element selector) respectively.

                                                                        document.addEventListener('DOMContentLoaded', function(){
                                                                            // Divi Menu(or Fullwidth Menu) module
                                                                            dvcsSmoothSubmenus.effect('.dvcs_smooth_submenus', '.et-menu-nav', '.et-menu');
                                                                        })

                                                                          Note that this time we’ve used CSS class selectors for all arguments (with the dot included).

                                                                          Remember that you should not use the same custom CSS class (or ID) for more than one menu module on the same page.

                                                                          If your header consists of more than one menu module and you want to apply the smooth submenus effect for all of them then you should assign different custom CSS classes (or IDs) for each and then call the effect() function for each individually.

                                                                          In such a case you will also need to use all those custom CSS classes and/or IDs in the menu modules custom CSS too, otherwise the effect won’t work as expected.

                                                                            Implementation: Divi MadMenu Module

                                                                              Implementing the smooth submenus effect for desktop menu created using Divi MadMenu extension is similar to Divi Menu and Fullwidth Menu modules implementation.

                                                                              Again, first we need to set the submenus animation to Fade In in the MadMenu Settings -> Content -> Desktop Menu -> Submenu Animation field.

                                                                              Next, let’s set the dvcs_madmenu_smooth_submenus custom CSS class in the MadMenu Settings -> Advanced -> CSS IDs & Classes -> CSS Class field and use it as the effect() function’s 1st argument.

                                                                              The 2nd and 3rd arguments for Divi MadMenu are .dvmm_menu_nav (the <nav> element selector) and .dvmm_menu (the <ul> element selector) respectively.

                                                                                document.addEventListener('DOMContentLoaded', function(){
                                                                                    // Divi MadMenu module
                                                                                    dvcsSmoothSubmenus.effect('.dvcs_madmenu_smooth_submenus', '.dvmm_menu_nav', '.dvmm_menu');
                                                                                })

                                                                                  Implementing the Smooth Submenus Effect for Multiple Divi Menus

                                                                                    Let’s assume that you are using all of the menus discussed above on the same page: Divi theme default menu as well as the menus created using Divi Menu module (or Fullwidth Menu module) and Divi MadMenu extension.

                                                                                    And you’d like to enable the smooth submenus effect for all of them.

                                                                                    In such a case you will do that the following way:

                                                                                      document.addEventListener('DOMContentLoaded', function(){
                                                                                          // Divi theme default menu
                                                                                          dvcsSmoothSubmenus.effect();
                                                                                      
                                                                                          // Divi Menu module menu (or Fullwidth Menu module menu)
                                                                                          dvcsSmoothSubmenus.effect('.dvcs_smooth_submenus', '.et-menu-nav', '.et-menu');
                                                                                      
                                                                                          // Divi MadMenu extension menu
                                                                                          dvcsSmoothSubmenus.effect('.dvcs_madmenu_smooth_submenus', '.dvmm_menu_nav', '.dvmm_menu');
                                                                                      })

                                                                                        As you can see we are enabling the effect for the menus by calling the effect() function for each of them individually and passing the necessary arguments to each call as explained above. You can do this for as many menus on a page as you need.

                                                                                          Final Thoughts

                                                                                            I’m not sure if “smooth submenus” is the best name for this effect but I think this effect will definitely make your website menu look more professional.

                                                                                            Go ahead and implement it for your website menu as explained in this tutorial, or subscribe to download and use the demo header template with this effect already enabled.

                                                                                            Hope you’ll like this effect, let me know your thoughts and suggestions in the comments section below.

                                                                                              View Live Demos & Get Divi MadMenu

                                                                                                Download FREE Divi Sections

                                                                                                    Subscribe To Our Newsletter

                                                                                                    Join our mailing list to download Divi freebies and get notified of our discounts, latest news and updates.

                                                                                                    You have Successfully Subscribed! Please confirm your email address.

                                                                                                    Divi MadMenu Coming Soon!

                                                                                                    Join our mailing list to get notified when the Divi MadMenu module is released! Check out the sneak peek...

                                                                                                    You have Successfully Subscribed! Please confirm your email address.

                                                                                                    Get FREE Divi Layouts

                                                                                                    Download 20+ Divi templates for FREE!

                                                                                                    Please confirm your email address to complete your subscription. Thank you!

                                                                                                    Black Friday Is Coming!

                                                                                                    Subscribe to get notified when our BIGGEST SALE starts!

                                                                                                    Please confirm your email address to complete your subscription. Thank you!

                                                                                                    Cyber Monday Is Coming!

                                                                                                    Subscribe to get notified when the SALE starts!

                                                                                                    Please confirm your email address to complete your subscription. Thank you!

                                                                                                    Black Friday Is Coming!

                                                                                                    Subscribe to get notified when our BIGGEST SALE starts!

                                                                                                    Please confirm your email address to complete your subscription. Thank you!