Why is an element with position: fixed moving with a non-positioned sibling?

With position: fixed, your header element is removed from the document flow.

The first in-flow element is main, which has margin-top: 90px in your code.

The parent of this element is body, which normally has a default margin: 8px (see HTML default style sheet).

Due to CSS margin collapsing, the body element’s margin-top: 8px is collapsed with the main element’s margin-top: 90px.

As a result, both elements, now having the same margin, shift down 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

The reason the fixed header moves is as follows:

  • Although the containing block for an element with position: fixed is the viewport…
  • The CSS offset properties (top, bottom, left and right) have an initial value of auto, which keeps the element where it normally would be if it were in the document flow.
  • Said another way, when you set an element to position: absolute or position: fixed (another form of position: absolute), you’re specifying the type of positioning you want… but you’re not positioning it anywhere.
  • It isn’t until you define the offsets that the element is actually positioned.
  • To shift the header to the top of the viewport, use 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

Leave a Comment