为什么一个元素有位置:固定移动与未定位的兄弟?

时间:2016-07-31 01:22:48

标签: html css css3 css-position

S.O.上有很多问题。这包括如何解决这个问题的答案(添加top: 0),但没有一个试图真正解释标题移动背后的原因。我更加好奇为什么会这样。

<header>Project Header</header> 
<main class="container" id="layout-mainContent">
    <div class="row" id="first-row">somecontent</div>
</main>

header {
   position: fixed;
}

#layout-maincontent {
   margin-top: 90px;  //moves header down.
}

同样问题的列表,但没有任何推理:

  1. Topmost 'fixed' position div moving with non position div
  2. margin affects other fixed elements position
  3. margin-top div causes fixed header div to move down
  4. 认为固定标题贴在浏览器窗口的顶部并且不应该因为另一个非定位的非子非父div(也称为兄弟)而移动似乎是合理的。 ESP。因为固定标题超出正常文档流程。 MDN on Fixed Positioning

    假设: 混淆源于固定元素相对于浏览器窗口的想法。这是事实,但是使用视口计算。视口使用常规文档流中的元素计算。因为文档流中的第一个div是非标题div,所以视口在应用margin-top之后开始。这只是猜测,我很乐意看到有人确认或纠正我。

1 个答案:

答案 0 :(得分:21)

使用position: fixed,您的header元素将从文档流中删除。

第一个流入元素为main,代码中包含margin-top: 90px

此元素的父级为body,通常具有默认margin: 8px(请参阅HTML default style sheet)。

由于CSS margin collapsingbody元素margin-top: 8pxmain元素的margin-top: 90px折叠在一起。

因此,现在具有相同边距的两个元素都向下移动90px。

html {
    background-color: green;
    height: 100%;
 }

body {
    background-color: pink;
    height: 100%;
}

header {
   position: fixed;
   border: 1px solid red;
}

main {
  margin-top: 90px;
  background-color:yellow;
}
<header>Project Header</header> 
<main class="container" id="layout-mainContent">
    <div class="row" id="first-row">somecontent</div>
</main>

jsFiddle

固定标题移动的原因如下:

  • 虽然position: fixed元素的containing block 是视口...
  • CSS偏移属性(topbottomleftright)的初始值为auto,可将元素保持在正常位置如果它在文件流程中就会存在。
  • 换句话说,当您将元素设置为position: absoluteposition: fixedposition: absolute的另一种形式)时,您将指定所需的定位类型... 但你没有把它放在任何地方。
  • 直到您定义元素实际定位的偏移量为止。
  • 要将标题移至视口顶部,请使用top: 0

html {
    background-color: green;
    height: 100%;
 }

body {
    background-color: pink;
    height: 100%;
}

header {
   position: fixed;
   border: 1px solid red;
   top: 0px; /* NEW */
}

main {
  margin-top: 90px;
  background-color:yellow;
}
<header>Project Header</header> 
<main class="container" id="layout-mainContent">
    <div class="row" id="first-row">somecontent</div>
</main>

jsFiddle