如何让我的汉堡包菜单直接出现在我的汉堡包图标下方?

How do I make my hamburger menu appear directly under my hamburger icon?

我想单击汉堡菜单图标,然后在我的图标下方显示列表。我用这种风格设置了我的汉堡包菜单图标

.menu-btn div {
    position: absolute;
    left: 100%;
    top: 64%;
    padding-right: 8px;
    margin-top: -0.50em;
    line-height: 1.2;
    font-size: 18px;
    font-weight: 200;
    vertical-align: middle;
    z-index: 99;
}

.menu-btn span {
    display: block;
    width: 20px;
    height: 2px;
    margin: 4px 0;
    background: #989da1;
    z-index: 99;
}

点击汉堡菜单后应该出现的选项菜单是

 <div class="responsive-menu">
    <ul id="menu">
       <li>Vote</li>
       <li>Search</li>
       <li>About</li>
       <li>Log In</li>
    </ul>
 </div>

但我不清楚如何设置汉堡菜单的样式,以便在您单击它时它直接出现在汉堡菜单下方。现在,它出现在屏幕顶部的中央——https://jsfiddle.net/wtp1k57b/1/。怎么设置这样的样式?

PS - 我正在寻找一种不依赖硬编码数字(例如顶部:27px)像素值的解决方案。在我的小 Fiddle 中让事情正常工作当然很好,但在我更广泛的应用程序中,我无法保证汉堡包菜单的大小。

使用 css 属性:topright 设置图标下元素的位置。

#menu
{
  position: absolute;
  top: 48px;
  right: 2px;

  background: #ededed;
  list-style-type: none;
}

将此 CSS 用于您的菜单 - 无边距,位置由 topright 设置定义:

#menu {
  position: absolute;
  width: 300px;
  margin: 0;
  padding: 50px;  
  background: #ededed;
  list-style-type: none;
  -webkit-font-smoothing: antialiased;
  top: 50px;
  right: 0;
}

https://jsfiddle.net/meuexde6/

我省略了测试的过渡,但您基本上应该将 right 参数从 -100px 设置为 0 以实现您似乎想要的效果。

评论后添加:

要定义菜单相对于按钮的位置,您必须将 position: relative 应用于它们的公共父元素 .mobile-nav。具有 position: absolute 的元素的位置值始终与具有 position: relative.

的第一个祖先相关

我根据这些更改了更新后 fiddle 中的值:

#menu {
  position: absolute;
  width: 300px;
  margin: 0;
  padding: 50px;  
  background: #ededed;
  list-style-type: none;
  -webkit-font-smoothing: antialiased;
  top: 40px;
  right: -32px;
}

已更新 fiddle:https://jsfiddle.net/meuexde6/1/

如果您真的希望菜单直接贴在按钮上(很难说 - 它没有边框),只需根据需要调整 topright 值即可。

那么,开始吧。我知道您正在寻求针对特定问题的解决方案,我很好地解决了它,但我不禁注意到您正在为自己的代码而苦苦挣扎。你必须简化你的思维方式,你的代码才会变得更精简。这个论坛的目的是帮助别人变得更好,对吧? :)

HTML

将菜单切换按钮保留在菜单外部是一种很好的做法 - 将解决很多问题 - 请查看下方内容。

除了 button 之外,使用其他任何东西作为切换功能在语义上都是不正确的,那么,为什么不在这里使用 button 呢?我还从您的代码中删除了不必要的混乱,例如一些 divid - id 可以与您的调用 class 进行交易。我还删除了 .mobile-nav,因为根本不需要它。

<button class="menu-btn">
  <span></span>
  <span></span>
  <span></span>
</button>

<div class="responsive-menu">
  <ul id="menu">
    <li>Vote</li>
    <li>Search</li>
    <li>About</li>
    <li>Log In</li>
  </ul>
</div>

CSS

我将 menu-btn 绝对定位在右上角,并给它一个 width 等于 #pageTitle height (我设置为 50px - a黄金标准)以保持矩形;根据经验,切换按钮是矩形的,并且始终与顶部导航栏的高度相同 - 在本例中为前面提到的 id。我对 .responsive-menu 所做的也是如此。我绝对定位它如下所示。这些更改使我能够删除很多 css 样式 - 现在已过时 - 例如 ul 菜单在 .responsive-menu 中的绝对定位.

.menu-btn {
  position:absolute;
  display:block;
  right:0;
  top:0;
  width:50px;
  height:50px;
  background:yellow;
  border:none;
  padding:16px;
}

.responsive-menu {
  position: absolute;
  top: 50px;
  right: 0;
  display: none;
}

Javascript

通过多年的实践,我意识到切换菜单而不是添加和删除 类 的最有效方法是在 body 标签上添加一个 class;如果您想根据菜单是否打开来重新设置页面上其他任何内容的样式,这可以帮助解决问题。

$('.menu-btn').on('click', function() {
  $('body').toggleClass('responsive-menu-open');
});

这是一个有效的 jsfiddle:https://jsfiddle.net/scooterlord/4atafhge/

我本可以做很多其他事情来进一步简化代码——删除不必要的 ID 和 类 因为大多数元素被认为是唯一的并且可以使用后代 类 来定位,例如 .responsive-menu ul,等。经过大量练习,您将设法更简单地思考并生成占用空间更小的代码。

编辑:关于您不喜欢 绝对 像素对齐的事实,这是一个技巧。

为父容器提供一个固定的 height,等于切换按钮的 - 在本例中为“#pageTitle”并将其位置设置为 relative 允许您使用 top:100%将响应式菜单正确放置在按钮正下方(高度基本相同):

#pageTitle {
  display: flex;
  height: 50px;
  position:relative;
}

.responsive-menu {
  position: absolute;
  top: 100%;
  right: 0;
  display: none;
}

这是更新后的 fiddle:https://jsfiddle.net/scooterlord/4atafhge/1/

编辑:娜塔莉亚,我想了想,这就是我的想法。我创建了一个绝对定位的 .menu-wrapper,在其中我放置了带有 float:right 的按钮和响应菜单并且没有定位 - 即它们是静态定位的。没有更多的像素值!耶!

.menu-wrapper {
  position:absolute;
  top:0;
  right:0;
}
.menu-btn {
  float:right;
  ...
}
.responsive-menu {
 float:right;
  clear:both; // to clear the .menu-btn and sit exactly below it
  ...
}

这是一个有效的 fiddle:https://jsfiddle.net/scooterlord/4atafhge/2/

HTML5 个语义元素。

details > summary {
  padding: 2px 6px;
  width:12px;
  border: none;
  list-style: none;
}

details > summary::-webkit-details-marker {
  display: none;
}

ul{
list-style: none;
margin-left:0;
padding-left:0;
}
<details>
  <summary>☰</summary>
  <ul>
  <li>a</li>
  <li>b</li>
  <li>c</li>
  </ul>
</details>

我想展示一种完全不同的方法而不使用 display: flex

HTML

在我看来,您的方法使用了太多包装器。你绝对可以减少 divs 的数量。此外,您应该始终尝试使用语义标签而不是 divul 等一般标签。考虑查看 this 文章。

因此,正如 已经提到的,您应该使用 button 作为汉堡包图标。此外,我建议使用 nav 而不是列表。

CSS

首先,为了提高清晰度,您应该将同一选择器的属性捆绑在同一位置。您不应该在应用通用选择器的地方分三个部分,而应该将它们合二为一。此外,不要将 box-sizing 设置为特定值,而是将其设置为 inherit,因此您始终可以为特定元素覆盖此值,而不必为其所有子元素都这样做。此外,我不明白你想在所有元素上使用 margin: 0 autobody 来实现什么。这对我来说没有任何意义。

既然你不想使用绝对定位,我强烈建议你避免使用像素作为测量单位。如果某些人因为视力不佳或其他原因而更改默认值 font-size,他们就会表现得很糟糕。相反,请考虑应用 remem% 等相对单位。通过将根元素的 font-size 设置为 62.5%,您仍然可以像使用像素一样进行计算 (1rem = 10px)。

正如我已经提到的,我避免将 display: flex 用于这种微不足道的事情。我不明白为什么此时要使用它。因此,我也不得不改变菜单按钮的位置。使用 topleft.

的百分比可以轻松定位导航

附带说明:您真的应该尝试只 post 相关的 CSS 代码——对我来说,第一步是删除所有不相关的部分。

最终解决方案

这是我最终的解决方案,没有 Flexbox,没有固定大小,也没有使用 px:

的绝对定位

$('.menu-btn').click(function() {
  $('nav').toggleClass('nav-open');
});
* {
  margin: 0;
  padding: 0;
  box-sizing: inherit;
}

html {
  font-size: 62.5%;
}

body {
  font: 1.6rem/1.4 Benton Sans, -apple-system, BlinkMacSystemFont, Roboto, Helvetica Neue, Helvetica, Tahoma, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  box-sizing: border-box;
}

header {
  width: 100%;
  background-color: orange;
  text-align: center;
  padding: 1rem;
  position: relative;
}

nav {
  display: none;
  width: 30rem;
  padding: 5rem;
  background-color: #ededed;
  position: absolute;
  right: 5%;
  top: 100%;
}

.nav-open {
  display: block;
}

nav a {
  display: block;
  width: 100%;
  text-align: center;
  padding: 1.4rem 1.6rem;
  text-decoration: none;
  cursor: pointer;
  font-size: 2.2rem;
  color: #000;
}

nav a:hover {
  background-color: #111;
  color: #fff;
}

.menu-btn {
  position: absolute;
  right: 5%;
  top: 50%;
  margin-top: -1.1rem;
  display: inline-block;
  cursor: pointer;
  border: none;
  outline: none;
  background-color: transparent;
}

@media only screen and (min-width: 500px) {
  .menu-btn, nav {
    display: none !important;
  }
}

.menu-btn span {
  display: block;
  width: 2rem;
  height: 0.2rem;
  margin: 0.4rem 0;
  background: #989da1;
  z-index: 99;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header>
  <h2>Page Title</h2>
  <button class="menu-btn">
    <span></span>
    <span></span>
    <span></span>
  </button>

  <nav>
    <a href="vote.html">Vote</a>
    <a href="search.html">Search</a>
    <a href="about.html">About</a>
    <a href="login.html">Log In</a>
  </nav>
</header>

或参见this fiddle。