There are a lot of questions on S.O. that cover the answer to how to fix this (add top: 0
), but none of them attempt to actually explain the reasoning behind the header movement. I'm more curious as to why this is the case.
<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.
}
List of like-questions but with no reasoning:
It seems reasonable to think that the fixed header sticks to the top of the browser window and should not move because of another non-positioned, non-child, non-parent div (aka sibling). Esp. because the fixed header is outside of normal document flow. MDN on Fixed Positioning
Hypothesis: The confusion stems from the idea that fixed elements are relative to the browser window. This is true, but is calculated using the viewport. The viewport is calculated using elements that are within the regular document flow. Because the first div that is within document flow is the non-header div, the viewport starts after the margin-top is applied. This is just speculation and I would love to see someone confirm or correct me.
An element with position: fixed; is positioned relative to the viewport, which means it always stays in the same place even if the page is scrolled. The top, right, bottom, and left properties are used to position the element.
It's now possible in modern browsers to position an element fixed relative to its container. An element that has a transform property acts as the viewport for any of its fixed position child elements.
Relative Positioning You can use two values top and left along with the position property to move an HTML element anywhere in the HTML document. Move Left - Use a negative value for left. Move Right - Use a positive value for left. Move Up - Use a negative value for top.
Position fixed doesn't work with transform CSS property. It happens because transform creates a new coordinate system and your position: fixed element becomes fixed to that transformed element. To fix the problem you can remove transform CSS property from the parent element.
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:
position: fixed
is the viewport...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.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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With