Site logo

Archived topic

Fixed 2nd level sub-menu

10 replies · Started by George on March 13, 2021

Viewing posts 1–11 of 11

I am trying to have the second-level sub-menu items stay fixed at the top position when their parent is being hovered over. I am attaching a URL as an example.

Hi there,

very complicated to do that.
Can't see a feasible way to do it on hover, but i tested this on arrow click:

.inside-navigation,
.main-navigation li {
  position: unset !important;
}
/* Position sub menu left of center */
.dropdown-click .main-navigation ul li.sfHover>ul.toggled-on {
  left: calc(50% - 300px);
  top: 100px;
}
/* Position sub sub menu right of center */
.dropdown-click .main-navigation ul li.sfHover>ul.toggled-on ul.toggled-on {
  position: absolute;
  left: calc(50% + 300px);
  top: 0;
}
/* Create grey white overlay */
.dropdown-click .main-navigation #menu-primary>li.sfHover:before {
  content: '';
  position: absolute;
  top: 60px;
  left: 0;
  right: 0;
  bottom: 0;
  background: linear-gradient(90deg, rgba(204, 204, 204, 1) 50%, rgba(255, 255, 255, 1) 50%);
  z-index: 1;
}

But in addition to this you would need some Javascript to first off close each sub menu when another is open - Tom provides some jQuery for that here:

https://generatepress.com/forums/topic/only-one-menu-open-at-a-time-in-the-submenu/page/2/#post-847826

And you would also need to some JS to add a body class when a sub menu is open. That class can the be used to add .custom-class body {overflow: hidden:} to prevent the body from scrolling when the sub menus are open.

Hi David.

It seems your code works fine on hover in my case. I believe the only issue I have is when hovering over a 1st level subdomain that's further down the list of sub-menu items and not being able to actually hover again on the second level. I have updated the private info with a staging URL for you to have a look at.

Updated with http access credentials since the site is a staging one and password protected.

Hi George,

Give this CSS a try:

.main-navigation:not(.toggled) ul ul li.sfHover>ul:after, .main-navigation:not(.toggled) ul ul li:hover>ul:after {
    content: "";
    top: 100%;
    left: 0;
    width: 100%;
    position: absolute;
    height: 800px;
}

Yes, it worked, thank you.

Is there a way to have a full-width background container that sits behind the menu while hovering over the items? Ideally, I would like the background container height to adjust according to the height of the 1st level sub-menu. Like the second URL, I attach.

Just to be clear you still want the same layout as per the example site for both the mega menu and the standard dropdowns?

Glad to hear its working with Hover - but personally i would go with Click as you're less likely to hit issues with large touch devices and you may find because this layout will require absolute positioning you'll generate a lot of CLS noise ( which should not occur on an onclick event - but does with hover ).

CSL noise: Are you referring to Cumulative Layout Shift in Web Core Vitals?

Thats correct.
If you use absolute position that changes on Hover it will register CLS. To avoid that the absolute position has to be the same when it is static as it is when its hovered.... if the option is set to Click then Google registers this as an expected event and ignores and CLS.

This is the CSS I currently use for the sub-menu with hover functionality. The only absolute positioning is found on the split sub-menu for the Categories menu. Could that cause CLS issues and if no, is there a way to apply the background container mentioned earlier?


/* Sub-menu */
.main-navigation ul ul li:not(:last-child) {
	border-bottom: 1px solid #828282;
}

.main-navigation ul ul {
    border: 1px solid #222;
    border-top: 0;
    box-shadow: 0 0 10px rgba(0,0,0,0.8);
}

/* Reverse direction on "Best Of" menu item */
.dropdown-hover .main-navigation:not(.toggled) ul .open-left ul {
    left: auto;
    right: 0;
	
}

.dropdown-hover .main-navigation:not(.toggled) ul .open-left li:hover>ul {
    left: auto;
    right: 100%;
}

.main-navigation .main-nav ul .open-left ul li.menu-item-has-children > a {
    padding-left: 0;
    padding-right: 20px;
}

.main-navigation ul .open-left ul .menu-item-has-children .dropdown-menu-toggle {
    float: left;
    padding-left: 20px;
    padding-right: 15px;
}

.dropdown-hover .open-left .sub-menu .dropdown-menu-toggle .gp-icon svg {
    transform: rotate(180deg);
}

/* Mega Menu */
@media (min-width: 769px) {
    nav .main-nav .mega-menu {
        position: static;
    }

    nav .main-nav .mega-menu > ul {
        position: absolute;
        width: 430px;

        display: flex;
        flex-wrap: wrap;
    }

    nav .main-nav .mega-menu>ul>li {
        display: inline-block;
        width: 25%;
        vertical-align: top;
    }

    nav .main-nav .mega-menu.mega-menu-col-2>ul>li {
        width: 50%;
    }

    nav .main-nav .mega-menu.mega-menu-col-3>ul>li {
        width: 33.3333%;
    }

    nav .main-nav .mega-menu.mega-menu-col-5>ul>li {
        width: 20%;
    }

    nav .main-nav .mega-menu ul .sub-menu {
        position: static;
        display: block;
        opacity: 1;
        visibility: visible;
        width: 100%;
        box-shadow: 0 0 0;
        left: 0;
        height: auto;
    }

    nav .main-nav .mega-menu ul.toggled-on .sub-menu {
        pointer-events: auto;
    }

    nav .main-nav .mega-menu .sub-menu .menu-item-has-children .dropdown-menu-toggle {
			display: none;
    }
}

/* 2nd level sub-menus at top */
.dropdown-hover .main-navigation:not(.toggled) ul .open-left ul li {
	position: unset;
}

If the Sub Menus absolute position doesn't change between static and hover then you would be fine.
What that means is that every Sub Menu elements should be absolute positioned before they are hovered on.

This archived topic is closed to new replies.