CSS "Fixed" Child Element Positions Relative to Parent Element Not to the Viewport, Why

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.

css fixed child element positions relative to parent element not to the viewport, why?

FWIW, when I ran into this, the problem turned out to be a parent div with -webkit-transform: translate3d(0, 0, 0) in its CSS. Apparently, this is a known source of potential mayhem in child elements with position: fixed.

For what I was trying to do (turning fixed on and off as a way of sticking a key nav element to the top of the page as it scrolled by), the solution was to append it to the page body element when it was time to hold it in place and sticking it back in its wrapper div when it wasn't. No idea if any of this would have helped the OP, but if you're chasing this bug yourself, worth looking into.

Element with position fixed is not sticking to parent element that has its position set to relative

position:fixed is not relative to parent element, even if it has a position:relative set. It's relative to the viewport. Here is what MDN says about it:

The element is removed from the normal document flow, and no space is created for the element in the page layout. It is positioned relative to the initial containing block established by the viewport, except when one of its ancestors has a transform, perspective, or filter property set to something other than none (see the CSS Transforms Spec), in which case that ancestor behaves as the containing block. (Note that there are browser inconsistencies with perspective and filter contributing to containing block formation.) Its final position is determined by the values of top, right, bottom, and left.

You would wanna use position:absolute instead if you want to position relative to parent element.

Child element positioned fixed relative to viewport

The position of the parent element or any ancestor is irrelevant when it comes to position:fixed. From the specification:

Fixed positioning is a subcategory of absolute positioning. The only difference is that for a fixed positioned box, the containing block is established by the viewport.

But there is some special cases where the containing block can change. It happens when using filter like I explained here, transform like explained here and sometimes will-change (explained here)


Concerning the use of top/left/bottom/right you need to consider the static position. If you don't set any of those values the browser will consider the static position to place the element. Still From the specification:

For the purposes of this section and the next, the term "static position" (of an element) refers, roughly, to the position an element would have had in the normal flow. More precisely ...

A position:fixed element always consider the viewport as its containing block (the reference for its placement) unless there is some particular properties used in a upper level (transform, filter, etc). The position of that element is either defined by top/left/right/bottom or by the static position like described in the specification.

Related question to get more details about the static position: Why aren't my absolutely-positioned elements located where I expect?

A fixed position child inside a relative parent renders not related to the parent in Chrome

Looks to me like you want the "absolute" position value instead of the "fixed" value, not sure why/when a change would have happened but according to w3c - Fixed: The element is positioned relative to the browser window. http://www.w3schools.com/cssref/pr_class_position.asp

http://jsfiddle.net/9q3v6/3/

 #parent-element{
border: 1px solid red;
height: 100px;
position: relative;
top: 50px;
width: 90%;
}
#child-element{
background-color: yellow;
height: 100px;
width: 100px;
position: absolute;
}

Fixed position on a child element doesn't take the viewport as it's containing block when some properties are present on the parent element

Here's where the spec says it: https://www.w3.org/TR/css-transforms-1/#containing-block-for-all-descendants

I'm not aware of any listing of similar properties.

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

CSS child with position: fixed not respecting parent layout

Here is a javascript approach which enables the header and footer to adopt a faux-fixed position relative to the scrollable parent.

Working Example:

var panel = document.getElementsByClassName('panel')[0];var panelHeader = panel.getElementsByTagName('header')[0];var panelFooter = panel.getElementsByTagName('footer')[0];
function fixElements() { var panelHeight = panel.clientHeight; var panelFooterHeight = panelFooter.clientHeight;
panelHeader.style.top = panel.scrollTop + 'px'; panelFooter.style.top = panel.scrollTop + panelHeight - panelFooterHeight + 'px';}
panel.addEventListener('scroll', fixElements, false);
.panel {display: inline-block;position: relative;width: 240px;height: 180px;overflow-x: hidden;overflow-y: auto;}
header, footer {display: block;position: absolute;left: 0;width: 240px;height: 24px;background-color: rgb(255, 0, 0);}
header {top: 0;}
footer {top: 156px;}
header code {padding-left: 6px;font-weight: bold;color: rgb(255, 255, 255);}
.panel p:first-of-type {padding-top: 12px;}
.panel p:last-of-type {padding-bottom: 12px;}
<div class="panel"><header><code>position: faux-fixed</code></header>
<p>Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, `and what is the use of a book,' thought Alice `without pictures or conversation?'</p>
<p>So she was considering in her own mind (as well as she could, for the hot day made her feel very sleepy and stupid), whether the pleasure of making a daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly a White Rabbit with pink eyes ran close by her.</p>
<p>There was nothing so very remarkable in that; nor did Alice think it so very much out of the way to hear the Rabbit say to itself, `Oh dear! Oh dear! I shall be late!' (when she thought it over afterwards, it occurred to her that she ought to have wondered at this, but at the time it all seemed quite natural); but when the Rabbit actually took a watch out of its waistcoat-pocket, and looked at it, and then hurried on, Alice started to her feet, for it flashed across her mind that she had never before seen a rabbit with either a waistcoat-pocket, or a watch to take out of it, and burning with curiosity, she ran across the field after it, and fortunately was just in time to see it pop down a large rabbit-hole under the hedge.</p>
<footer></footer></div>

Fixed element positioning relative to its parent

'normally' position fixed fixes relative to the viewport.

But there are exceptions. See MDN

The element is removed from the normal document flow, and no space is created for the element in the page layout. It is positioned relative to the initial containing block established by the viewport, except when one of its ancestors has a transform, perspective, or filter property set to something other than none (see the CSS Transforms Spec), in which case that ancestor behaves as the containing block. (Note that there are browser inconsistencies with perspective and filter contributing to containing block formation.) Its final position is determined by the values of top, right, bottom, and left.

Here's a simple example:

body {}

.parent {
position: relative;
margin: 100px;
transform: scale(1);
width: 50vw;
height: 10vw;
background: black;
rfilter: blur(1);
}

.child {
position: fixed;
top: 0px;
left: 0px;
width: 100px;
height: 100px;
background-color: blue;
}
<body>
<div class="parent">
<div class="child"></div>
</div>
</body>


Related Topics



Leave a reply



Submit