如何制作像 Stack Overflow 那样的菜单

How to Make a Menu Like Stack Overflow's

我真的很喜欢 Stack Overflow 在顶部完成下拉菜单的方式。请注意您如何必须 单击才能触发下拉菜单,但您仍然必须 悬停才能获得下拉菜单。还有一些似乎是组的东西——一旦你点击,悬停将激活图片中显示的菜单。这很难解释,但如果你玩一会你就会明白我的意思。此外,重要的是,在用户再次点击关闭之前,最后一个悬停的菜单将一直显示。

这是我目前所拥有的;请注意,我几乎具有相同的功能,除了悬停的最后一个菜单不会保持下降状态(它在 mouseout 时关闭,而不是在关闭单击之前关闭)并且切换功能是粗略的:

$(document).ready(function() {
  var depressed = false;

  $('.menu').click(function() {
    depressed = true;
    $('.menu').toggleClass('active');
  });
  $('.menu').hover(function() {
    if (depressed) {
      $('.menu').toggleClass('active');
    }
  });
});
ul {
  margin: 0;
  padding: 0;
}
ul li {
  display: inline-block;
  padding: 10px 20px;
  background: #333;
  color: #eee;
}
ul li.active:hover ul {
  display: block;
}
ul li ul {
  display: none;
  position: absolute;
  border: 2px solid #555;
}
ul li ul li {
  display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
  <li class="menu">button 1
    <ul>
      <li>sub button 1</li>
      <li>sub button 2</li>
    </ul>
  </li>
  <li class="menu">button 2
    <ul>
      <li>sub button 1</li>
      <li>sub button 2</li>
    </ul>
  </li>
  <li class="menu">button 3
    <ul>
      <li>sub button 1</li>
      <li>sub button 2</li>
    </ul>
  </li>
</ul>

我的 JS 没有被切割 git。 那么,解决此问题的最佳方法是什么?

$(document).ready(function() {

  $('#M1').click(function() {
    $('#M1').toggleClass('active');
    $('#M2').removeClass('active');
    $('#M3').removeClass('active');
  });
  $('#M2').click(function() {
    $('#M2').toggleClass('active');
    $('#M1').removeClass('active');
    $('#M3').removeClass('active');
  });
  $('#M3').click(function() {
    $('#M3').toggleClass('active');
    $('#M1').removeClass('active');
    $('#M2').removeClass('active');
  });
  
});
ul {
  margin: 0;
  padding: 0;
}
ul li {
  display: inline-block;
  padding: 10px 20px;
  background: #333;
  color: #eee;
}
ul li.active ul {
  display: block;
}
ul li ul {
  display: none;
  position: absolute;
  border: 2px solid #555;
}
ul li ul li {
  display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
  <li class="menu" id='M1'>button 1
    <ul>
      <li>sub button 1</li>
      <li>sub button 2</li>
    </ul>
  </li>
  <li class="menu" id='M2'>button 2
    <ul>
      <li>sub button 1</li>
      <li>sub button 2</li>
    </ul>
  </li>
  <li class="menu" id='M3'>button 3
    <ul>
      <li>sub button 1</li>
      <li>sub button 2</li>
    </ul>
  </li>
</ul>

这对我有用。

我刚刚删除了 .active 末尾的 :hover class 并为每个按钮创建了一个单独的功能。

我没看过SO菜单,不知道他们是怎么做到的。但这似乎很好用。

单击其中一个按钮可打开下拉菜单。

下拉菜单不会像您的代码中那样被 'mouseout' 关闭,而是仅当悬停另一个菜单时才会关闭。如果您将鼠标悬停在菜单区域之外,最后悬停的菜单将保持打开状态。

点击任意位置关闭菜单。

因此显示菜单并不是直接通过在 CSS 中使用 :hover 伪元素来完成的,而是通过添加 class 来完成的,即使菜单未悬停时它仍然存在。我认为最终结果与 Stack Overflow 的结果非常接近。

$(function(){

  // The event to handle clicks outside of the menu. This will close the menu.
  var offEvent = 
    function(event){
      $('.menu-bar').removeClass('active');
      $(document).off('click', offEvent);
    };

  // The click event on the menu buttons, to toggle 'menu mode' as it were.
  $(document).on('click', '.menu-bar .menu', 
    function(event){
      event.preventDefault();
      $('.menu-bar').addClass('active');
      $(this).addClass('active');
     
      // Leave menu mode by clicking anywhere of the menu.
      $(document).on('click',
        offEvent
        );
    });
  
  // Hover toggles between the dropdowns of the separate menus.
  $('.menu-bar .menu').hover( 
    function(event){
      var $current = $(this);
      $('.menu').each(
        function(index, element){
          var $element = $(this);
          if ($element.get(0) == $current.get(0)) {
            $element.addClass('active');
          } else {
            $element.removeClass('active');
          }
        });
    });
});
ul {
  margin: 0;
  padding: 0;
}

ul li {
  display: inline-block;
  padding: 10px 20px;
  background: #333;
  color: #eee;
}

ul li ul {
  display: none;
  position: absolute;
  border: 2px solid #555;
}

ul li ul li {
  display: block;
}

.menu .dropdown {
  display: none;
}
.menu-bar.active .menu.active .dropdown {
  display: block;
}

.menu {
  display: inline-block;
  position: relative;
  border: 1px solid grey;
}

.menu .dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  border: 2px solid #555;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="menu-bar">
  <li class="menu">button 1
    <ul class="dropdown">
      <li>sub button 1</li>
      <li>sub button 2</li>
    </ul>
  </li>
  <li class="menu">button 2
    <ul class="dropdown">
      <li>sub button 1</li>
      <li>sub button 2</li>
    </ul>
  </li>
  <li class="menu">button 3
    <ul class="dropdown">
      <li>sub button 1</li>
      <li>sub button 2</li>
    </ul>
  </li>
</ul>