在可滚动容器中定位绝对位置下拉菜单

9
是否可以让绝对定位的下拉菜单保持在可滚动容器的顶部,并随着相对定位父元素一起滚动而移动?目前,下拉菜单出现在可滚动区域内。
下面的截图是我想要实现的效果。如果需要,我也可以接受JavaScript解决方案。

enter image description here

{{link1: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>


个人而言,我会将导航放在可滚动容器之外,并将整个导航包装在一个带有固定位置和顶部为0的标题div中,然后在下面放置其他元素! - Phillip Dews
有趣的是,用户何时会同时展开菜单并水平滚动? - sol
@PhillipDews 你能否基于这个fiddle提供一个示例?另外,我想指出导航栏不在网站页眉中,它将用于页面中间的一个部分。 - Stickers
@sol 很好的问题,我认为当下拉菜单移动到视口外时,它将被隐藏,或者我可以在外部容器上设置溢出隐藏。 - Stickers
2个回答

3

一种简单的方法是将下拉列表的位置固定,但是要确保相应地应用左和上值。另一种方法是追加下拉菜单到ul元素之外,这样它出现时就不会被包裹在其中。

.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>

编辑

我添加了另一个不使用固定位置的代码片段。它在打开时根据父元素偏移量更改其坐标。

$('#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>


2
当下拉菜单设置为固定位置时,它将不再随父级项目一起滚动;一旦您应用左、上值,它将相对于视口而非父级项目。 - Stickers
我添加了另一个片段,它不使用固定位置。它根据父偏移量在打开时更改其坐标。 - orabis

1
这里提供使用jQuery的选项。
基本上,就像其他人提到的那样,您需要将子导航项移出主导航的包装器,以便它们不被隐藏。
我们可以将它们放在自己的包装器中,该包装器具有与主导航包装器类似的标记,并使用数据元素将它们匹配起来,以允许单击显示/隐藏。
然后,当我们滚动主导航栏时,我们可以将子导航包装器同步到该元素的滚动位置,使得子导航项似乎固定在主导航项上。
最后,我们可以使用CSS隐藏子导航包装器的滚动条。
下面的代码片段应该可以给您一个大致的想法,然后您可以根据需要进行样式设置,使其看起来更像主要和次要导航项连接在一起。
单击主导航中的导航项,然后向侧面滚动以查看其效果:

$(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 A.A</li>
      <li>Sub Item A.B</li>
      <li>Sub Item A.C</li>
    </ul>
    <ul class="subnav" data-id="two">
      <li><a>Sub Item B.A</a></li>
    </ul>
    <ul class="subnav" data-id="three">
      <li><a>Sub Item C.A</a></li>
      <li><a>Sub Item C.B</a></li>
    </ul>
    <ul class="subnav" data-id="four">
      <li><a>Sub Item D.A</a></li>
      <li><a>Sub Item D.B</a></li>
    </ul>
    <ul class="subnav" data-id="five">
      <li><a>Sub Item E.A</a></li>
      <li><a>Sub Item E.B</a></li>
    </ul>
  </div>
</div>

<script
  src="https://code.jquery.com/jquery-3.2.1.min.js"
  integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
  crossorigin="anonymous"></script>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接