Why Is an Element with Position: Fixed Moving with a Non-Positioned Sibling

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>

position fixed div in absolute positioned div works - but why?

An element with position: fixed is indeed positioned relative to the viewport (or browser). However, because it is an absolutely positioned element, it is "positioned relative to the initial containing block established by the viewport".

This is laid out in the position documentation:

An absolutely positioned element is an element whose computed position value is absolute or fixed. The top, right, bottom, and left properties specify offsets from the edges of the element's containing block. (The containing block is the ancestor relative to which the element is positioned.) If the element has margins, they are added to the offset.

That is to say, when you specify margin-top and margin-left, these values are relative to the parent. And because the element is positioned relative to the parent, the default top and left are inherited from the parent. In your example, the .fixed element has a top value of 100px because it inherits the top value of 100px from .sidebar (the parent). When you set top: 0 on .fixed, you are overriding this value (going from top: 108px to top: 0):

Fixed

Because of this, the element appears to be taken 'out of flow'. However, it is still always positioned relative to the viewport; it just had an initial offset (which it inherited from its parent).

Fixed position but relative to container

Short answer: no. (It is now possible with CSS transform. See the edit below)

Long answer: The problem with using "fixed" positioning is that it takes the element out of flow. thus it can't be re-positioned relative to its parent because it's as if it didn't have one. If, however, the container is of a fixed, known width, you can use something like:

#fixedContainer {
position: fixed;
width: 600px;
height: 200px;
left: 50%;
top: 0%;
margin-left: -300px; /*half the width*/
}

http://jsfiddle.net/HFjU6/1/

Edit (03/2015):

This is outdated information. It is now possible to center content of an dynamic size (horizontally and vertically) with the help of the magic of CSS3 transform. The same principle applies, but instead of using margin to offset your container, you can use translateX(-50%). This doesn't work with the above margin trick because you don't know how much to offset it unless the width is fixed and you can't use relative values (like 50%) because it will be relative to the parent and not the element it's applied to. transform behaves differently. Its values are relative to the element they are applied to. Thus, 50% for transform means half the width of the element, while 50% for margin is half of the parent's width. This is an IE9+ solution

Using similar code to the above example, I recreated the same scenario using completely dynamic width and height:

.fixedContainer {
background-color:#ddd;
position: fixed;
padding: 2em;
left: 50%;
top: 0%;
transform: translateX(-50%);
}

If you want it to be centered, you can do that too:

.fixedContainer {
background-color:#ddd;
position: fixed;
padding: 2em;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}

Demos:

jsFiddle: Centered horizontally only

jsFiddle: Centered both horizontally and vertically

Original credit goes to user aaronk6 for pointing it out to me in this answer

Topmost 'fixed' position div moving with non position div

Change the CSS of the your .bottom element to:

.bottom {
position:relative;
top:128px; #64+64
}

Why absolute positioned element looks at its sibling element?

position:absolute; looks for the nearest element with position:relative/absolute, and makes his position, based on that element.

In your case, as you have position:relative in the image, the "Irene" text will be placed at the top left corner of the image.

For "Irene" to be at the top left of the document, you either apply position:fixed, wich is based on the browser window, or remove all the position:absolute/relative that are above the "Irene" element.

Why is an absolutely positioned element placed by its sibling instead of at the top corner of the page?

I always thought that absolute positioned elements are out of the flow.

Yes, they are removed from normal flow.

I don't understand why absolute positioned element appeared after child_static div.

Just because absolute positioning removes elements from normal flow, it doesn't mean it does alter the position of the elements as well.

In other words, absolutely positioned elements would be at the same place as they are not positioned absolutely unless their top, left, ... offsets are set.

So what happens is that they would overlap next sibling elements, because they are not part of document flow anymore.

For instance have a look at the following example where the gold <div> element is covered by absolutely positioned element.

.parent {    position: relative;}
.child_static { height: 20px; background: blue;}
.child_absolute { position: absolute; height: 20px; width: 100%; background: green;}
.child_static ~ .child_static { background: gold;}
<div class='parent'>    <div class='child_static'>Green</div>    <div class='child_absolute'>Blue</div>    <div class='child_static'>Gold</div></div>

Can I position an element fixed relative to parent?

Let me provide answers to both possible questions. Note that your existing title (and original post) ask a question different than what you seek in your edit and subsequent comment.


To position an element "fixed" relative to a parent element, you want position:absolute on the child element, and any position mode other than the default or static on your parent element.

For example:

#parentDiv { position:relative; }
#childDiv { position:absolute; left:50px; top:20px; }

This will position childDiv element 50 pixels left and 20 pixels down relative to parentDiv's position.


To position an element "fixed" relative to the window, you want position:fixed, and can use top:, left:, right:, and bottom: to position as you see fit.

For example:

#yourDiv { position:fixed; bottom:40px; right:40px; }

This will position yourDiv fixed relative to the web browser window, 40 pixels from the bottom edge and 40 pixels from the right edge.

Adding p to one div, is moving other div

It's because you're not positioning the element anywhere vertically, because you're not setting any of its top or bottom offsets, thus placing it where it would be positioned if it were part of the document flow. This means it will align itself with the first element in the document flow, according to its margin.

That first element in document flow happens to be <p>.

The proper fix for your problem is setting top:0; on the fixed element. For a more detailed explanation please read the accepted answer of the question yours duplicates.

Other possible (improper, IMHO) "fixes" are adjusting the first element in document flow to start from the top of the document, by overriding the default margins of <p> to 0, or setting it's display property to inline-block (or any other inline type of display).



Related Topics



Leave a reply



Submit