【问题标题】:How do I make my hamburger menu appear directly under my hamburger icon?如何让我的汉堡菜单直接显示在我的汉堡图标下方?
【发布时间】:2018-02-06 18:33:48
【问题描述】:

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

.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 中让事情发挥作用是件好事,但在我更广泛的应用程序中,我无法保证汉堡菜单的大小。

【问题讨论】:

  • 在你想要的位置设置菜单的position。您已经将其设置为绝对,所以现在设置顶部和左侧属性
  • @JoshKisb,“top”和“left”似乎只接受像素值,但我想稍微不那么死板,并以某种方式告诉菜单只出现在图标下方。跨度>
  • 菜单按钮/图标是绝对定位的,所以对菜单做同样的事情
  • @JoshKisb,我不理解“做同样的事情”。你的意思是放一个“位置:绝对;”导航菜单上的属性就像这个 -- jsfiddle.net/wtp1k57b/4 ?

标签: html css display hamburger-menu


【解决方案1】:

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

HTML

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

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

CSS

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

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

正如我已经提到的,我避免将display: flex 用于这种微不足道的事情。我不明白为什么现在应该使用它。因此,我也不得不改变菜单按钮的位置。使用topleft 的百分比可以轻松定位导航。

附带说明:您真的应该尝试只发布相关的 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>

或者见thisfiddle。

【讨论】:

    【解决方案2】:

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

    #menu
    {
      position: absolute;
      top: 48px;
      right: 2px;
    
      background: #ededed;
      list-style-type: none;
    }
    

    【讨论】:

    • 有没有办法在不硬编码固定像素值(例如“48px”)的情况下做到这一点?我希望它出现在正下方 - 例如汉堡菜单结束的地方
    • 您可以使用相对单位(如emrem等)并根据父元素确定值。跨度>
    【解决方案3】:

    为您的菜单使用此 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 的第一个祖先相关。

    我根据这些更改了更新的小提琴中的值:

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

    更新小提琴:https://jsfiddle.net/meuexde6/1/

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

    【讨论】:

    • 谢谢。我编辑了我的问题以使愿望更加清晰。我不希望硬编码“top”和“right”的值,而是以某种方式告诉下拉菜单出现在汉堡菜单结束的任何地方。我意识到 50px 可能在我的 JSFiddle 演示中有效,但我不能保证这将是我实际应用程序中的大小。
    • 请注意我的答案和更新的小提琴
    【解决方案4】:

    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>

    【讨论】:

    • 谢谢。我喜欢这个解决方案 b/c 你不是在任何地方硬编码数字。但是我很难弄清楚如何将它应用到我所拥有的东西上。关键是采用菜单项中的“
        ”元素并将您的“::-webkit-details-marker”样式应用于它吗?
    • 您照常使用无序列表。 HTML5 details 元素简单地为您完成所有繁重的工作,即,实现代码很简单。不用担心::-webkit-details-marker 无关紧要。
    • 我仍然缺少一些东西,因为即使在我删除了所有定位样式元素并根据“详细信息”和“摘要”构建了我的内容之后,列表仍然显示在顶部对齐并且在我的汉堡菜单左侧 -- jsfiddle.net/wtp1k57b/6 .
    • margin 和/或 padding 在 CSS 中的 ul 上。如果这不起作用,请尝试设置实际的 li 项目边距/填充样式。
    • 边距/填充只是控制文本的间距,不是吗?也许我要问的需要一个单独的问题。我会尝试这样做,看看有什么结果。
    【解决方案5】:

    所以,就这样吧。我知道您正在寻求针对特定问题的解决方案,我已经解决了,但我不禁注意到您正在为您的代码而苦苦挣扎。您必须简化您的思维方式,您的代码将变得更精简。这个论坛的目的是帮助别人变得更好,对吧? :)

    HTML

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

    除了button 之外的切换功能在语义上是不正确的,那么,为什么不在这里使用button 呢?我还从您的代码中删除了不必要的混乱,例如一些divs 和id - 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 - 一个黄金标准)以使其保持矩形;根据经验,切换按钮是矩形的,并且始终与顶部导航栏的高度相同——在这种情况下是前面提到的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 等。经过很多通过实践,您将设法更简单地思考并生成占用空间更小的代码。

    编辑:关于你不喜欢 absolute 像素在这里对齐的事实是一个技巧。

    给父容器一个固定的height,等于切换按钮的-在这种情况下'#pageTitle'并将其位置设置为relative允许您使用top:100%将响应式菜单正确放置在下方按钮(基本上是相同的高度):

    #pageTitle {
      display: flex;
      height: 50px;
      position:relative;
    }
    
    .responsive-menu {
      position: absolute;
      top: 100%;
      right: 0;
      display: none;
    }
    

    这是一个更新的小提琴:https://jsfiddle.net/scooterlord/4atafhge/1/

    编辑:Natalia,我想了一下,这就是我想出的。我创建了一个绝对定位的.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
      ...
    }
    

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

    【讨论】:

    • 所以我了解您的解决方案,您为“#pageTitle”元素硬编码“高度”,为“h2”元素硬编码“行高”?我想taht让我更接近。但是为什么我们必须在某个地方硬编码一个像素数呢?在 CSS 中不可能告诉一个元素出现在另一个元素下方而不告诉该元素另一个结束的位置?
    • @Natalia 是的,您可以,但如果您希望所有内容都正确对齐,则不能在这种情况下。如果不涉及定位,您只需将一个放在另一个下方并切换该元素。
    • @Natalia 检查我回答中的附加部分,我认为这正是您所追求的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多