Absolute disclosure of a position in a scrollable container

Is it possible to make the position of the absolute drop-down list on top of the scrollable container and move with the relative parent of the position when scrolling? A drop-down menu appears right now in the scroll area.

The screenshot below is what I want to achieve. I can also open javascript solutions if necessary.

enter image description here

jsFiddle

.navbar { padding-left: 0; white-space: nowrap; overflow: auto; } .navbar-item { position: relative; margin-left: 0; list-style: none; display: inline-block; width: 200px; text-align: center; border: 1px solid; } .dropdown { position: absolute; padding-left: 0; width: 200px; box-shadow: 0 1px 0 1px black; display: none; } .dropdown-item { margin-left: 0; list-style: none; } .navbar-item:hover .dropdown { display: block; } 
 <ul class="navbar"> <li class="navbar-item"> <a>Item A</a> <ul class="dropdown"> <li class="dropdown-item">Sub Item A</li> <li class="dropdown-item">Sub Item B</li> <li class="dropdown-item">Sub Item C</li> </ul> </li> <li class="navbar-item"><a>Item B</a></li> <li class="navbar-item"><a>Item C</a></li> <li class="navbar-item"><a>Item D</a></li> <li class="navbar-item"><a>Item E</a></li> </ul> 
+7
javascript jquery html css
source share
2 answers

The jQuery option is used here.

In principle, as others have already noted, you will have to move the subnav elements outside the main shell so that they are not hidden.

We can put them in our own shell, which has the same markup for the main shell, and then match them using a data element that allows you to show / hide when clicked.

Then, when we scroll the main navigation bar, we can synchronize the subnav shell with this scrollbar of the element, so the subnav elements are apparently tied to the main navigation elements.

Finally, we can hide the scrollbar of the subnav shell using CSS.

The snippet below should give you a general idea, then you can stylize it if necessary so that it looks more like connecting primary and secondary navigation elements.

Click the navigation item in the main navigator, then scroll to the side to see it in action:

 $(function(){ var navbar = $('.navbar'); var subnavBar = $('.subnavs-wrapper .scrollbar-hider'); $(navbar).find('li').each(function(){ var dataId = $(this).attr('data-id'); var matchingUl = $(this).parent().next().find('ul[data-id="' + dataId + '"]'); $(this).on('click', function(){ $(matchingUl).css('visibility') == 'hidden' ? $(matchingUl).css('visibility', 'visible') : $(matchingUl).css('visibility', 'hidden'); }); $(navbar).on('scroll', function(){ $(subnavBar).scrollLeft($(this).scrollLeft()); }); }); }); 
 .navbar { padding-left: 0; white-space: nowrap; overflow: auto; display: flex; } .navbar-item { position: relative; margin-left: 0; list-style: none; flex-shrink: 0; width: 200px; text-align: center; border: 1px solid; } .dropdown { position: absolute; padding-left: 0; width: 200px; box-shadow: 0 1px 0 1px black; display: none; } .navbar-item { margin-left: 0; list-style: none; } .navbar-item:hover .dropdown { display: block; } .subnavs-wrapper { overflow: hidden; /* hide scrollbar */ } .subnavs-wrapper .scrollbar-hider { display: flex; overflow: auto; padding-bottom: 50px; /* hide scrollbar */ margin-bottom: -50px; /* hide scrollbar */ } .subnav { width: 200px; padding-left: 0; list-style: none; visibility: hidden; flex-shrink: 0; border: 1px solid black; } 
 <ul class="navbar"> <li class="navbar-item" data-id="one"><a>Item A</a> <li class="navbar-item" data-id="two"><a>Item B</a></li> <li class="navbar-item" data-id="three"><a>Item C</a></li> <li class="navbar-item" data-id="four"><a>Item D</a></li> <li class="navbar-item" data-id="five"><a>Item E</a></li> </ul> <div class="subnavs-wrapper"> <div class="scrollbar-hider"> <ul class="subnav" data-id="one"> <li>Sub Item AA</li> <li>Sub Item AB</li> <li>Sub Item AC</li> </ul> <ul class="subnav" data-id="two"> <li><a>Sub Item BA</a></li> </ul> <ul class="subnav" data-id="three"> <li><a>Sub Item CA</a></li> <li><a>Sub Item CB</a></li> </ul> <ul class="subnav" data-id="four"> <li><a>Sub Item DA</a></li> <li><a>Sub Item DB</a></li> </ul> <ul class="subnav" data-id="five"> <li><a>Sub Item EA</a></li> <li><a>Sub Item EB</a></li> </ul> </div> </div> <script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script> 
+1
source share

An easy way is to make the position of the dropdown file fixed, but remember to apply the left and top values ​​accordingly. Another way is to add a drop-down menu outside the ul element, so when it appears, it will not be completed inside it.

 .dropdown { position: fixed; } 

 .navbar { padding-left: 0; white-space: nowrap; overflow: auto; } .navbar-item { position: relative; margin-left: 0; list-style: none; display: inline-block; width: 200px; text-align: center; border: 1px solid; } .dropdown { position: fixed; background-color: #fff; padding-left: 0; width: 200px; box-shadow: 0 1px 0 1px black; display: none; } .navbar-item { margin-left: 0; list-style: none; } .navbar-item:hover .dropdown { display: block; } 
 <ul class="navbar"> <li class="navbar-item"> <a>Item A</a> <ul class="dropdown"> <li class="dropdown-item">Sub Item A</li> <li class="dropdown-item">Sub Item B</li> <li class="dropdown-item">Sub Item C</li> </ul> </li> <li class="navbar-item"><a>Item B</a></li> <li class="navbar-item"><a>Item C</a></li> <li class="navbar-item"><a>Item D</a></li> <li class="navbar-item"><a>Item E</a></li> </ul> 

Edit

I added another snippet that does not use a fixed position. It changes its coordinates when opening based on the parental offset.

 $('#menu1, #submenu1').mouseover(function(event) { $('#submenu1').addClass("show").css($('#menu1').offset()); }); $('#menu1, #submenu1').mouseleave(function(event) { $('#submenu1').removeClass("show"); }); 
 .navbar { padding-left: 0; white-space: nowrap; overflow: auto; } .navbar-item { position: relative; margin-left: 0; list-style: none; display: inline-block; width: 200px; text-align: center; border: 1px solid; } .dropdown { position: absolute; padding-left: 0; width: 200px; box-shadow: 0 1px 0 1px black; display: none; } .dropdown.show { display: block; margin-left: 1px; background-color: #fff; } .dropdown-item { margin-left: 0; list-style: none; } .navbar-item:hover .dropdown { display: block; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <ul class="navbar"> <li id="menu1" class="navbar-item"> <a>Item A</a> </li> <li class="navbar-item"><a>Item B</a></li> <li class="navbar-item"><a>Item C</a></li> <li class="navbar-item"><a>Item D</a></li> <li class="navbar-item"><a>Item E</a></li> </ul> <ul id="submenu1" class="dropdown"> <li class="dropdown-item">Sub Item A</li> <li class="dropdown-item">Sub Item B</li> <li class="dropdown-item">Sub Item C</li> </ul> 
+3
source share

All Articles