105

I have 3 div elements.

1st div is bigger (wrap) and has position:relative;

2nd div is positioned absolute to the 1st div relative positioning (and is included in the 1st div)

3rd div is contained in the 2nd div and also has absolute positioning.

<div id="1st">
   <div id="2nd">
     <div id="3rd"></div>
   </div>
</div>

Why is the 3rd div position absolute to the 2nd div (which is also absolute position to the 1st div) and not to 1st div that has relative position ?

Because the 3rd div is absolute positioning to the absolute positioned 2nd div.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
pufos
  • 2,890
  • 8
  • 34
  • 38

6 Answers6

108

Because position: absolute resets the relative position for children just as position: relative does.

There is no way around this - if you want the third div to be absolutely positioned relatively to the first one, you will have to make it a child of the first one.

Pekka
  • 442,112
  • 142
  • 972
  • 1,088
  • So basically the absolute position become relative position for it's absolute positioned child ? – pufos May 08 '11 at 14:39
  • @pufos kind of. The `0px / 0px` position for children gets reset by the `position: absolute` – Pekka May 08 '11 at 14:41
  • 29
    @pufos I think you're confusing this a little. `position:relative` means that element will be positioned (using top, right, bottom left) relatively from its current position. `position: absolute` means it will be positioned relative to browsers window or first parent with `position: absolute` or `position: relative`. – seler May 08 '11 at 14:43
  • Can you share a reference to this online ? Because i couldn't find any ... And ... Thanks a lot – pufos May 08 '11 at 14:45
  • 2
    @pufos the very basic reference is here: http://www.w3.org/TR/CSS2/visuren.html#choose-position – Pekka May 08 '11 at 14:46
  • @seler - that's a really succinct way to explain that – Adam Tolley Mar 09 '12 at 01:28
32

Both position:relative and position:absolute establish containing elements as positioning ascestors.

If you need div 3 to be positioned based on div 1 then make it a direct child of div 1.

Note that position: relative means the element is positioned relative to its natural position and position: absolute means the element is positioned relative to its first position:relative or position:absolute ancestor.

Mike Tunnicliffe
  • 10,674
  • 3
  • 31
  • 46
  • I wanted the 3rd div to be absolute positioned to the absolute positioned div but i did't know if this is standard (crossbrowser) .. and i couldn't find specifications online ... Thanks a lot – pufos May 08 '11 at 14:44
  • Absolute positioning in that section: http://www.w3.org/TR/CSS21/visuren.html#comp-abspos – Mike Tunnicliffe May 08 '11 at 14:48
  • @MikeTunnicliffe absolute means element is positioned relative to its first position:fixed also – Trần Kim Dự May 01 '15 at 19:38
15

Position static: the static position is the default way an element will appear in the normal flow of your HTML file if no position is specified at all.

Important: top, right, bottom and left properties HAVE NO EFFECT ON A STATICALLY POSITIONED ELEMENT.

Position relative: positioning an element with the relative value keeps the element (and the space it occupies) in the normal flow of your HTML file.

You can then move the element by some amount using the properties left, right, top and bottom. However, this may cause the element to overlap other elements that are on the page—which may or may not be the effect that you want.

A relatively positioned element can move from its spot, but the space it occupied remains.

Position absolute: applying the absolute position value to an element removes it from the normal flow. When you move the absolute positioned element, its reference point is the top/left of its nearest containing element that has a position declared other than static—also called its nearest positioning context. So, if no containing element with a position other than static exists, then it will be positioned from the top-left corner of the body element.

In your case 3rd's nearest containing container is 2nd.

Paolo
  • 20,112
  • 21
  • 72
  • 113
Gaurav
  • 821
  • 9
  • 11
6

Yet another clarifying answer.

Your current scenario is this:

#my-parent {position: absolute}
#my-parent .my_child {position: absolute}

And you're kind of struggling with it.

If you can change the HTML, simply do this:

#my-parent {position: absolute}
#my-parent .my-wrapper {position: relative}        /* Since you've added the wrapper in HTML */
#my-parent .my-wrapper .my-child {position: absolute}  /* Now you can play with it */
valk
  • 9,363
  • 12
  • 59
  • 79
  • 2
    my-wrapper probably should be .my-wrapper – jdavid.net Dec 14 '13 at 02:47
  • This approach is amazing, I still have no idea why it solved my problem. My problem is that I can't have my third element to be child of the first element due to some other reason. – windmaomao May 31 '18 at 14:17
3

The reason why the 3rd div element is absolutely positioned to the 2nd div element is because as the CSS spec explains here, is because the "parent" element (better said: containing block) of an absolutely positioned element is not necessarily its immediate parent element, but rather its immediate positioned element i.e. any element whose position is set to anything but static for example position: relative/absolute/fixed/sticky;

Hence, whenever possible in your code, if you want the 3rd div element be absolutely positioned in regards to the 1st div you should make your 2nd div element as position: static; which is its default value (or just simply remove any position: ... declaration in the rule set of your 2nd div element).

The above will make the 1st div the containing block of the 3rd absolutely positioned div, ignoring the 2nd div for this positioning purpose.

Hope it helps.

atzom
  • 31
  • 5
  • what you mentioned, [here exact url](https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block), thanks this is what I'm looking for. – devstefancho Jan 31 '21 at 14:23
0

In case anyone is still looking for an answer to this.

I was able to achieve this result by adding a clear: both; style to the first absolutely positioned div which reset the child and allowed it to use it's own absolute positioning.

ttrasn
  • 4,322
  • 4
  • 26
  • 43