怎样使我的汉堡菜单直接出现在我的汉堡图标下方?

5
我希望能够点击汉堡菜单图标,然后在图标下方显示列表。我使用以下样式设置了我的汉堡菜单图标。
.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-我正在寻找一种解决方案,不依赖于硬编码数字(例如 top:27px)像素值。当然,在我的小Fiddle中使事情正常工作很好,但在我的更广泛应用中,我不能保证汉堡菜单的大小。

将菜单的 位置 设置为您想要的位置。您已经将其设置为绝对定位,现在请设置 top 和 left 属性。 - JoshKisb
@JoshKisb,“top”和“left”似乎只接受像素值,但我想要更灵活一些,以某种方式告诉菜单只出现在图标下方。 - user7055375
菜单按钮/图标是绝对定位的,所以在菜单上执行相同操作。 - JoshKisb
@JoshKisb,我不理解“只需做相同的事情”的意思。你是指在导航菜单上添加“position:absolute;”属性,就像这样 - https://jsfiddle.net/wtp1k57b/4/? - user7055375
5个回答

0

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>


谢谢。我喜欢这个解决方案,因为你没有在任何地方硬编码数字。但是我在尝试将其应用到我的代码时遇到了困难。关键是获取我拥有的菜单项的"<UL>"元素,并将你的"::-webkit-details-marker"样式应用于它吗? - user7055375
您可以像平常一样使用无序列表。HTML5的details元素会为您处理所有繁重的工作,也就是说,它的代码实现非常简单。不用担心::-webkit-details-marker,它与此无关。 - Ronnie Royston
在你的CSS中为ul设置margin和/或padding。如果这不起作用,请尝试为实际的li项设置margin / padding样式。 - Ronnie Royston
边距/填充只是控制文本间距的,对吧?也许我所问的需要另一个问题。我会尝试这样做以查看结果。 - user7055375
好的。我的要求清晰吗?我不想让其他人感到困惑,也觉得我还没有弄清楚我的问题。 - user7055375
显示剩余2条评论

0

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

HTML

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

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

CSS

首先,为了提高清晰度,您应该将相同选择器的属性捆绑在同一位置。您不应该有三个部分应用通用选择器,而是将其合并为一个部分。此外,不要将box-sizing设置为特定值,而是将其设置为inherit,这样您就可以始终覆盖特定元素的此值,而无需为其所有子元素执行此操作。此外,我不明白您想通过在所有元素和body上使用margin: 0 auto来实现什么目的。对我来说没有任何意义。
既然您不想使用绝对定位,我强烈建议您避免使用像素作为测量单位。如果某些人因视力差或其他原因更改默认的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>

或者查看this的代码片段。


0
使用CSS属性:topright来设置元素在图标下方的位置。
#menu
{
  position: absolute;
  top: 48px;
  right: 2px;

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

有没有办法在不硬编码固定像素值(例如“48px”)的情况下实现这一点?我希望它出现在正下方——例如,在汉堡菜单结束的地方。 - user7055375
你可以使用相对单位(如_em_,_rem_等),并基于父元素确定值。 - Joel García

0

使用此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;
}

更新的 JSFiddle:https://jsfiddle.net/meuexde6/1/

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


谢谢。我编辑了我的问题以使需求更加清晰。我不想为“top”和“right”硬编码值,而是希望以某种方式告诉下拉菜单出现在汉堡菜单结束的地方。我意识到50px可能在我的JSFiddle演示中有效,但我不能保证在我的实际应用程序中这将是大小。 - user7055375
请注意我的回答中的补充和更新后的 fiddle。 - Johannes

0

好的,开始吧。我知道你正在寻求解决特定问题的方案,我已经解决了它,但我注意到你在苦苦挣扎着。你必须简化你的思考方式,你的代码就会变得更加简洁。这个论坛的目的是帮助其他人变得更好,对吧? :)

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设置为与#pageTitleheight相等(我将其设置为50px-黄金标准),以保持其矩形形状。应该有一个经验法则,即切换按钮应该是矩形的,并且始终与顶部导航栏具有相同的高度-在这种情况下是前面提到的id。对于.responsive-menu,我也做了同样的事情。如下所示,我将其绝对定位。这些更改使我能够删除许多CSS样式-现在已过时-例如在.responsive-menu内部绝对定位ul菜单。

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

编辑: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”元素上硬编码了一个“height”,并在“h2”元素上设置了一个“line-height”?我想这让我更接近了解。但是为什么我们必须在某个地方硬编码像素数?在CSS中不可能告诉一个元素出现在另一个元素下面而不告诉该元素另一个元素的结束位置吗? - user7055375
@Natalia 是的,你可以这样做,但如果你想要所有东西都对齐,那么在这种情况下就不行了。如果没有涉及到定位,你可以将一个元素放在另一个元素下面,并切换它。 - scooterlord
@Natalia,请查看我回答中的附加部分,我认为那正是你想要的。 - scooterlord

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