为什么当 position:absolute 应用于 header 时,导航中需要 float:left 以保持文本居中?

Why is float:left required in navigation to keep text center when position:absolute applied to header?

在header中观察到CSS position : absolute的一个奇怪的事情是,除非下面的菜单中有float:left,否则菜单的文本不会垂直居中,而是停留在最佳。您可以通过 运行 此页面中给出的全宽代码段来查看。我已经为 float:none in lower screen width 设置了一个媒体查询,它取消了更高 screen-widths 中的 float:left

现在,为什么会出现这种行为?当 position:absolute 应用于 header 和 vice-versa 时,为什么 float:left 保持菜单文本垂直居中?我在搜索时没有找到任何内容。

编辑 -

有些回答说这是由于 "collapsing" 的页边距造成的。但他们没有解释为什么 h1 of header 不是 "collapsing" 并且以这种方式表现?为什么只有 h1 of menu 是 "collapsing" ?它似乎更像是一些元素的选择重叠而不是折叠。

编辑2-

请答题者,如果为了解释的方便,要将摘录分解,除了部分摘录外,还应将完整的摘录或其修改部分放入他们的答案中。因为 divs 不是孤立行动的。答案应该有 header 和 position: absolute,它的 h1 和 margin-top 应用于 header 下面的 div 的 h1。

请看这个片段 -

div.header {
    position: absolute;
    left: 0%;
    top: 0%;
    width: 100%;
    height: auto;
    text-align: center;
    color: #EE82EE;
    background-color: #000000;
}
.submenu {
 text-align: center;
  width:100%;
  margin:0;
  margin-top: 72px;
  color:black;
  height: 100px;
  background-color: red;
  float: left;
  padding:0px;
}
@media screen and (max-width: 766px){
  .submenu {
   float:none;
  }
}
<div class="header">
 <h1>HEADER </h1>
</div>
<div class="submenu">
  <h1>MENU</h1>
  
</div>

编辑

正如我在评论中解释的那样,header 中的 h1 不会折叠,因为它使用 position:absolute - 正如您在下面看到的那样,它是修复以防止折叠边距。重叠只是因为你的 header 是绝对定位的,所以它会出现在页面中其他所有内容的顶部。

概括地说,当 垂直 边距触及 元素时,会发生 折叠边距它们之间没有分隔(例如边框或填充),没有浮动没有绝对定位未固定并具有overflow:visible(默认值)。还有一些其他情况,但这涵盖了绝大多数原因,包括您的原因。


回答

您看到的是折叠边距的效果。

CSS 规范说,当两个元素的垂直边距接触时,两个边距将合并为一个边距。

当第一个(或最后一个)child 和 parent 之间没有分隔时,parent/child 元素也会发生这种情况 - 在这种情况下,折叠边距最终会超出parent.

在您的情况下,您的h1 具有浏览器样式表的默认边距。这被折叠到它的 parent 的边距中,即默认情况下 submenu 元素,因为它是一个块元素。

防止边距折叠
有多种方法可以防止 child 的边距折叠,包括:

  • 浮动
  • 位置:绝对。
  • 将显示更改为以下之一:“table-cell”、“table-caption”或“inline-block”。
  • 添加可见以外的溢出,例如overflow:auto
  • 在parent和child之间添加一个"separation",例如边框或填充。

当您将 float 添加到您的 child 时,这是防止边距折叠的方法之一,因此您的边距仍然有 space 出现在h1 的顶部包含单词 "Menu".

查看一些示例:

.submenu {
 text-align: center;
  width:100%;
  margin:0;
  margin-top: 0px;
  color:black;
  height: 100px;
  background-color: red;
  float: none;
  padding:0px;
}
.container { border:2px solid #ff0;}
.container:after {
  content: "";
  display: table;
  clear: both;
}
h1{ margin:30px 0;}
.submenu.hasfloat {float: left;}
.submenu.hasoverflow {overflow: auto;}
<p>The top margin of this h1 is collapsed into the parent's margin. </p><p>The parent's top margin is 10px, and the h1 has a top margin of 30px, so when collapsed the parent now takes on the child's margin because it is larger - you can see the margin surrounded with the yellow border:</p>
<div class="container">
<div class="submenu">
  <h1>Collapsed</h1>
</div>
</div>
<p>The top margin of this h1 isn't collapsing because the parent is <b>floated</b>:</p>
<div class="container">
<div class="submenu hasfloat">
  <h1>Not collapsed</h1>
</div>
</div>
<p>The top margin of this h1 isn't collapsing because the parent has <b>overflow:auto</b> (i.e. any value other than visible):</p>
<div class="container">
<div class="submenu hasoverflow">
  <h1>Not collapsed</h1>
</div>
</div>


示例:显示即使 header 不是绝对定位问题仍然存在。

div.header {
    position: relative;
    left: 0%;
    top: 0%;
    width: 100%;
    height: auto;
    text-align: center;
    color: #EE82EE;
    background-color: #000000;
}
.submenu {
 text-align: center;
  width:100%;
  margin:0;
  margin-top: 72px;
  color:black;
  height: 100px;
  background-color: red;
  float: left;
  padding:0px;
}
@media screen and (max-width: 766px){
  .submenu {
   float:none;
  }
}
<div class="header">
 <h1>HEADER <small>- position:relative</small></h1>
</div>
<div class="submenu">
  <h1>MENU <small>- top margin is still collapsing</small></h1>
  
</div>

参考资料:从以下位置阅读有关折叠边距的更多信息:

应用于 header 的 position: absolute 使 div 固定,而所有其他 div 变得相对可移动。所以,为了让其他人也固定下来,我们给他们一些其他的属性,比如 display:inline-block,float:left 等

此外,需要给绝对div下方的div一个margin-top来抵消折叠边距

请查看应用了这些修复的工作代码,其中包含 https://codepen.io/anon/pen/QqRgRB

中的所有 div

摘录如下-

div.header {
    position: absolute;
    left: 0%;
    top: 0%;
    width: 100%;
    height: auto;
    text-align: center;
    color: #EE82EE;
    background-color: grey;
}
.menu {
 text-align: center;
  width:100%;
  margin:0;
  margin-top: 72px;
  color:black;
  height: 100px;
  background-color: red;
  float: left;
  padding:0px;
  display: inline-block;
}
.submenu {
   text-align: center;
  width:100%;
  margin:0;
  margin-top: 0px;
  color:black;
  height: 100px;
  background-color: yellow;
  display:inline-block;
  padding:0px;
}
@media screen and (max-width: 766px){
  .menu {
   float:none;
  }
}
body {
  margin:0px;
}
<div class="header">
 <h1>HEADER </h1>
</div>
<div class="menu">
  <h1>MENU</h1>
  
</div>

<div class="submenu">
  <h1>SUBMENU</h2>
</div>