skip to Main Content

Our shopping site has a dropdown menu with main categories and sub-categories. When you hover over a main category, the sub-category menu pops out on the right. The issue is that both menus are contained in the same scrolling container. So you scroll down to find a main category below the current viewport, you hover over a main category and the sub-category pops up on the left, but you have scrolled down, so you only see part of none of the sub-categories. So our current fix, which is not really working is to scroll the container to the top of the sub-categories, which is also the top of the categories. So now your mouse is over a different category and a different set of sub-categories pop out. So basically you cannot view sub-categories for categories below the viewport. Ideally we would make them seperate containers with seperate scrollbars. But that will not look good at all and will not be acceptable.

Note: This only happens when the browser window height is shrunk far enough to cause a vertical scroll bar. Obviously if the window is big enough, no scroll bar is needed and we have no issues.

Here is what it currently looks like. You hover over the ‘Electrical’ category and the sub-category pops out to the right.
enter image description here

We are using javascript and vue.js, no jquery. I learned this code will scroll the sub-category menu into view, which is not what we want.

var el = document.querySelector('.nav-flyout-menu');
      el.scrollIntoView(true);

I think what I want is to actually move, as in set style.top of the sub-category menu to top of the current viewport. I played around with that a little and couldn’t anything to work right. Does anyone know how we can successfully solve this issue. Is setting the style.top dynamically the best method? How do I figure out what to set it to? I have tried something like this:

var topBound = document.querySelector('.nav-flyout-menu').getBoundingClientRect().top;
if(topBound < 0) {
  let newTop = Math.abs(topBound) + 42;
  document.querySelector('.nav-flyout-menu').style.top = newTop + "px";
}

This code worked sometimes and sometimes not.

Update: As requested, here is a fiddle that I have created showcasing my issue. It is not exactly like our site, but I think it is close enough. Make the example height small enough to force a scroll bar and hover over each category. When you scroll down to view the bottom categories, you won’t be able to see the top of the subcategories. That is exactly the problem we are currently facing. I think I want to change the top value when it shows the current subcategory. But I can’t figure out how to calculate that top value. I used jQuery just to whip out the fiddle example, but we are not using jQuery on our site.

$("a.dropdown-item").hover(
	function () {
    $(".nav-flyout-menu").removeClass("show");
    let category = $.trim($(this).text());
    category = category.replace(/s+/g, '-').toLowerCase();
    $("." + category).addClass("show");
  }, 
  function () {
    
  }
)
.navbar {
  width: 100%;
  display: flex;
  position: relative;
  padding: 0.5rem 1rem;
  background-color: #0000cc;
  flex-direction: row;
}
.navbar a {
  color: #ffffff;
}
.navbar .dropdown-menu a {
  color: #000000;
}
ul {
  list-style: none;
}

.dropdown-menu {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 1000;
  display: block;
  float: left;
  min-width: 10rem;
  padding: .5rem 0;
  margin: 0;
  font-size: 1rem;
  color: #212529;
  text-align: left;
  list-style: none;
  background-color: #fff;
  background-clip: padding-box;
  border: 1px solid rgba(0,0,0,.15);
  border-bottom: .5rem solid #cc0000;
  padding-right: 1.5rem;
}
.navbar-nav .dropdown-menu {
    position: static;
    float: none;
}
.navbar-container .dropdown-menu {
    max-height: calc(100vh - 150px);
    overflow-y: auto;
}
.dropdown-item {
    display: block;
    width: 100%;
    padding: .5rem 1.5rem;
    clear: both;
    text-align: inherit;
    white-space: nowrap;
    background-color: transparent;
    border: 0;
}
.nav-flyout-root {
    position: relative;
    display: inline-block;
    float: left;
}
.nav-flyout-menu {
    display: none;
    flex-direction: column;
    float: left;
    min-width: 10rem;
    padding: .5rem 0;
    margin: 0;
    font-size: 1rem;
    color: #212529;
    text-align: left;
    list-style: none;
    background-color: #fff;
    background-clip: padding-box;
}
.nav-flyout-menu.show {
  display: inline-flex;
}
.flyout-menu-item {
    font-weight: 400;
    color: #212529;
    text-align: inherit;
    white-space: nowrap;
    background-color: transparent;
    border: 0;
    display: block;
    width: 100%;
    padding: .5rem 1.5rem;
    clear: both;
}
.submenu div {
  display: block;
}
.dropdown-item:focus, .dropdown-item:hover, .dropdown-item a:focus, .dropdown-item a:hover {
    color: #fff!important;
    text-decoration: none;
    background-color: #430984;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.2.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="navbar-container">
  <div class="navbar">
    <ul>
      <li>
        <a href="#">First</a>
        <div class="dropdown-menu">
          <div class="d-flex">
            <div class="nav-flyout-root">
              <a class="dropdown-item">
                Computers
              </a>
              <a class="dropdown-item">
                Laptops
              </a>
              <a class="dropdown-item">
                Monitors
              </a>
              <a class="dropdown-item">
                Hard Drives
              </a>
              <a class="dropdown-item">
                Keyboards
              </a>
              <a class="dropdown-item">
                Mice
              </a>
              <a class="dropdown-item">
                Computers
              </a>
              <a class="dropdown-item">
                Laptops
              </a>
              <a class="dropdown-item">
                Monitors
              </a>
              <a class="dropdown-item">
                Hard Drives
              </a>
              <a class="dropdown-item">
                Keyboards
              </a>
              <a class="dropdown-item">
                Mice
              </a>
            </div>
            <div class="nav-flyout-menu position-relative computers">
              <div class="flyout-menu-header text-nowrap">
                <a href="#">All Computers</a>
              </div>
              <div class="d-flex flex-grow-1 flex-column submenu">
                <div>
                  <a href="#" class="flyout-menu-item">Dell</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">HP</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Asus</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Compaq</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Dell</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Samsung</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Acer</a>
                </div>
              </div>
            </div>
            <div class="nav-flyout-menu position-relative laptops">
              <div class="flyout-menu-header text-nowrap">
                <a href="#">All Laptops</a>
              </div>
              <div class="d-flex flex-grow-1 flex-column submenu">
                <div>
                  <a href="#" class="flyout-menu-item">Acer</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">HP</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Sony</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Compaq</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Vaio</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Apple</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Acer</a>
                </div>
              </div>
            </div>
            <div class="nav-flyout-menu position-relative monitors">
              <div class="flyout-menu-header text-nowrap">
                <a href="#">All Monitors</a>
              </div>
              <div class="d-flex flex-grow-1 flex-column submenu">
                <div>
                  <a href="#" class="flyout-menu-item">Qnix</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">HP</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Sony</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Dell</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Asus</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">22"</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">23"</a>
                </div>
              </div>
            </div>
            <div class="nav-flyout-menu position-relative hard-drives">
              <div class="flyout-menu-header text-nowrap">
                <a href="#">All Hard Drives</a>
              </div>
              <div class="d-flex flex-grow-1 flex-column submenu">
                <div>
                  <a href="#" class="flyout-menu-item">Western Digital</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Samsung</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">HP</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Seagate</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Kingston</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Crucial</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">SSD</a>
                </div>
              </div>
            </div>
            <div class="nav-flyout-menu position-relative keyboards">
              <div class="flyout-menu-header text-nowrap">
                <a href="#">All Keyboards</a>
              </div>
              <div class="d-flex flex-grow-1 flex-column submenu">
                <div>
                  <a href="#" class="flyout-menu-item">Logitech</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Microsoft</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Gearhead</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Razer</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Cherry MX</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Mech Blue</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Mech Red</a>
                </div>
              </div>
            </div>
            <div class="nav-flyout-menu position-relative mice">
              <div class="flyout-menu-header text-nowrap">
                <a href="#">All Mice</a>
              </div>
              <div class="d-flex flex-grow-1 flex-column submenu">
                <div>
                  <a href="#" class="flyout-menu-item">Steel Series</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Microsoft</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Logitech</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Razer</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Cooler Master</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">HyperX</a>
                </div>
                <div>
                  <a href="#" class="flyout-menu-item">Roccat</a>
                </div>
              </div>
            </div>
          </div>
        </div>
      </li>
    </ul>
  </div>
</div>

2

Answers


  1. Chosen as BEST ANSWER

    Finally got this! I knew this had to be able to be accomplished with some simple javascript. I was right. Element.scrollTop was the key. I don't think this would be possible with CSS alone, someone correct me if I am wrong. We have an event listener for when a main menu item is hovered to show the submenu. In that listener, I put this code:

    let scrollTop = vm.$el.parentElement.parentElement.parentElement.scrollTop;
    document.querySelector('.nav-flyout-menu').style.top = scrollTop + "px";
    

    This seems to be working in all my tests.


  2. You can add a class to the active sub-menu element

    var el = document.querySelector('.nav-flyout-menu');
    el.classList.add("nav-active-sub-menu");
    

    And control it’s style with css. Something like:

    .nav-active-sub-menu{
        position: absolute;
        top: 0;
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search