Break an Absolutely Positioned Element Out of Its Relatively Positioned Ancestor

Break an absolutely positioned element out of its relatively positioned ancestor?

You can use a bit of javascript to do this (I'm assuming you can't change the markup?).

document.body.appendChild(document.getElementById('i_want_to_be_absolute_to_body'));

This absolute positioned element is not positioned next to it's nearest ancestor and instead attached to the document body and I'm wondering why

The part you're missing is this:

An element with position: absolute; is positioned relative to the nearest positioned ancestor (instead of positioned relative to the viewport, like fixed).

The words_info element has ancestors, but it doesn't have any positioned ancestors (elements with position: relative, position: absolute, or position: fixed). So it's defaulting to this:

However; if an absolute positioned element has no positioned ancestors, it uses the document body, and moves along with page scrolling.

Why is this absolutely positioned element not positioning relative to its container?

Absolutely positioned elements are positioned with respect to the edges of their containing block, which is defined as the first ancestor that is not position: static.

None of the ancestor elements are position: static, so it is with respect to the initial position of the viewport.

Set position: relative on the .container elements if you really want to absolutely position them.

That said, it looks like you would be better off doing this instead:

.child {
margin-left: 0.2ex;
}

CSS - prevent absolute positioned element from overflowing body

You have to work with nested divs which have all some different responsibility:

The outermost sets the position with left and right simultaniously. The right:0 sets it to the right.

The inner div is the real content div, which sets the width.

Here is a demo: http://jsfiddle.net/atnc3/44/

<div class="abs-position">
<div class="abs-content">
Absolut Vodka
</div>
</div>

.abs-position {
position:absolute;
right:0;
left: 300px;
overflow: hidden;
}
.abs-content {
width: 400px;
}

.abs-position {    position:absolute;    right:0;    left: 300px;    overflow: hidden;    /* following: just for demonstration purposes */    padding: 5px;    border: 1px solid gold;    opacity: 0.8;}.abs-content {    width: 400px;    /* following: just for demonstration purposes */    padding: 5px;    background: lightgray;}.container {    width: 600px;    background: cornflowerblue;}
<div class="abs-position">    <div class="abs-content">         Absolut Vodka           </div></div><div class="container">Other content<br>Other content<br>Other content<br>Other content<br></div>

Is there anything wrong with positioning all elements relatively?

Yes, it is. If you try to position one element absolute it is positioned relatively to the closest ancestor, which has a CSS position other than static.

If every element has position:relative, this would be the direct parent.

But you might want to position the absolute element relatively to an element further up in the DOM tree or maybe absolutely on the page body.

At some point you will have the situation where you are not in full control of the HTML. Then you will see, that it is counterproductive to set everything relative.

An example might be a phat layer menu. You have the layer inside a .menu class somewhere deep in the jungle of hierarchical ul li elements. This should be positioned relative to the .menu element's position. You might not want to change the DOM tree here.

Why aren't my absolutely/fixed-positioned elements located where I expect?

To correctly understand this, you need to refer to the official specification where you find the equation the element must satisfy:

'top' + 'margin-top' + 'border-top-width' + 'padding-top' + 'height' + 'padding-bottom' + 'border-bottom-width' + 'margin-bottom' + 'bottom' = height of containing block

We don't have any border and padding so in your case it will simply be:

'top' + 'margin-top' + 'height' + 'margin-bottom' + 'bottom' = height of containing block

And if you read under you will find this:


  1. 'top' and 'bottom' are 'auto' and 'height' is not 'auto', then set 'top' to the static position, set 'auto' values for 'margin-top' and 'margin-bottom' to 0, and solve for 'bottom'.

So in your case, you have set a height and kept top/bottom to auto thus top will be set to static position

..More precisely, the static position for 'top' is the distance from the top edge of the containing block to the top margin edge of a hypothetical box that would have been the first box of the element if its specified 'position' value had been 'static'..

To make it easy, it's the position of the element if you didn't set position:absolute.

Here is an easy illustration to better understand

.container {
background: lightblue;
position: relative;
padding:40px 20px;
display:inline-block;
vertical-align:top;
width: 250px;
}

.box-grey {
background: grey;
height: 100px;
width: 100px;
position: absolute;
}

.box-green {
height:20px;
background:green;
}
<div class="container">
<div class="box-green"></div>
<div class="box-grey" style="position:static;">I am static</div>
</div>

<div class="container">
<div class="box-green"></div>
<div class="box-grey">I am absolute</div>
</div>

Why does absolute position ignore elements with static positions?

For one thing, the premise is incorrect. There are situations where a statically positioned element can provide the containing block of an absolutely positioned element. position, transform, will-change and contain are all properties that will cause an element to establish an absolute positioning containing block

For example:

.outer {
width:50vw;
height:50vh;
background-color:lightblue;
margin: 25vh 25vw;
transform:translateX(0);
}
.inner {
position:absolute;
width:100px;
height:50px;
inset: 0;
background-color:red;
}
  <div class="outer">
<div class="inner"></div>
</div>

Absolute positioning ignoring padding of parent

First, let's see why this is happening.

The reason is that, surprisingly, when a box has position: absolute its containing box is the parent's padding box (that is, the box around its padding). This is surprising because usually (that is, when using static or relative positioning) the containing box is the parent's content box.

Here is the relevant part of the CSS specification:

In the case that the ancestor is an inline element, the containing block is the bounding box around the padding boxes of the first and the last inline boxes generated for that element.... Otherwise, the containing block is formed by the padding edge of the ancestor.

The simplest approach—as suggested in Winter's answer—is to use padding: inherit on the absolutely positioned div. It only works, though, if you don't want the absolutely positioned div to have any additional padding of its own. I think the most general-purpose solutions (in that both elements can have their own independent padding) are:

  1. Add an extra relatively positioned div (with no padding) around the absolutely positioned div. That new div will respect the padding of its parent, and the absolutely positioned div will then fill it.

    The downside, of course, is that you're messing with the HTML simply for presentational purposes.

  2. Repeat the padding (or add to it) on the absolutely positioned element.

    The downside here is that you have to repeat the values in your CSS, which is brittle if you're writing the CSS directly. However, if you're using a pre-processing tool like SASS or LESS you can avoid that problem by using a variable. This is the method I personally use.

CSS Filter cancels element position

That's because absolutely positioned elements are positioned relatively to their containing block, which is established by their nearest positioned ancestor, or the initial containing block if there is no such ancestor.

Then, if you don't use filter, the containing block will be the initial one, which has the same dimensions as the viewport.

However, if you use filter on body, that will establish a containing block, even for absolutely positioned descendants. It will be like if you used position: relative.