Using position:absolute, the nearest positioned ancestor is having no effect
Asked Answered
C

2

5

I have a parent and a child div. Parent has one image. Child div has another image. Child image needs to appear in top-left corner of parent image for which I thought to set position of child image to absolute and parent's position to some non-static position, say relative or absolute. (I set left and top too but let's forget about it for now.)

This is because setting absolute for the child should work only if its first ancestor is positioned non-statically as according to W3Schools absolute means The element is positioned relative to its first positioned (not static) ancestor element.

But I noticed that even if I don't set position of the parent (i.e. its position will be "static" by default), event then the child image still gets positioned nicely in top-left.

Can someone help me understand why I don't have to set position of the parent to some non-static value in order for the absolute property to work properly? or did I understand working of absolute incorrectly?

<div class="parent">
    <img src="https://lh4.ggpht.com/wKrDLLmmxjfRG2-E-k5L5BUuHWpCOe4lWRF7oVs1Gzdn5e5yvr8fj-ORTlBF43U47yI=w300">
  <div class="child">
    <img src="http://xiostorage.com/wp-content/uploads/2015/10/test.png" width="200">
  </div>
</div>

/*.parent {
  position:relative;
}*/

.child {
  display:none;
  position:absolute;
  left:0;
}
.parent:hover .child {
  display:initial;
}

Here is the JSFiddle code.

Update: Connexo helped with following updated code.

Try uncommenting the position for parent to unlock the mystery. Accepted answer has more information.

<h1>
   Positioning test
</h1>
<div class="parent">
    <img src="https://lh4.ggpht.com/wKrDLLmmxjfRG2-E-k5L5BUuHWpCOe4lWRF7oVs1Gzdn5e5yvr8fj-ORTlBF43U47yI=w300">
  <div class="child">
    <img src="http://xiostorage.com/wp-content/uploads/2015/10/test.png" width="200">
  </div>

/*
.parent {
  position:relative;
}*/

.child {
  display: none;
  position: absolute;
  left: 0;
  top: 0;
}
.parent:hover .child {
  display:initial;
}
Cynic answered 11/3, 2017 at 22:37 Comment(5)
But I noticed that even if I don't set position of the parent (i.e. its position will be "static" by default), event then the child image still gets positioned nicely in top-left. Now try the same with right: 0; instead of left: 0; and you get closer to the mystery.Bigley
The element is positioned relative to its first positioned (not static) ancestor element. And if there is none, to the body. Which in your examples share the top left corner with div.parent.Bigley
jsfiddle.net/ghbnfa6o/2Bigley
@connexo, not body. The initial containing block, or HTML / viewport.Veinule
@Bigley Your first comment didn't help me reach near the mystery but the jsfiddle example did help because of the new H1 tag introduced. :) Thanks.Cynic
V
8

Two general rules to keep in mind:

  • An absolutely positioned element will be positioned within its containing block, which is defined by the nearest positioned ancestor. However, if there is no positioned ancestor, the containing block is the initial containing block (i.e., the viewport).

    Your .parent div is pretty much aligned at the top-left corner of the viewport. That's why your absolutely positioned child will have similar positioning in either containing block.

  • When you apply position: absolute to an element you remove it from the normal flow. That's it. The element will still be positioned as though it were in the normal flow. It isn't until you apply the CSS offset properties (left, right, top, bottom) that you actually position the element.

Veinule answered 11/3, 2017 at 22:55 Comment(3)
Thanks @Michael_B. Can you kindly tell what you mean by viewport? What is viewport in my code?Cynic
For all intents and purposes, it's the html element (also known as the root element). For a detailed explanation, see: w3.org/TR/CSS22/visudet.html#containing-block-detailsVeinule
Is it possible to find the positioned containing block for absolutely positioned element using css or javascript? (For example add a border to the block.) If yes then how? :) ThanksParonymous
M
1

You forgot setting top in your JSFiddle so all it did was get aligned to the left side of the page, where your image was as well. As soon as you add top: 0px in your JSFiddle you will notice that the image does end up in the top left corner of the page.

Below a simple demo with top added and a margin pushing the .parent away from the corner.

.parent {
  margin: 30px;
  /* position: relative;*/
}
.child {
  display:none;
  position:absolute;
  left:0;
  top:0;
}
.parent:hover .child {
  display:initial;
}
<div class="parent">
    <img src="https://lh4.ggpht.com/wKrDLLmmxjfRG2-E-k5L5BUuHWpCOe4lWRF7oVs1Gzdn5e5yvr8fj-ORTlBF43U47yI=w300">
  <div class="child">
    <img src="http://xiostorage.com/wp-content/uploads/2015/10/test.png" width="200">
  </div>
</div>
Mailable answered 11/3, 2017 at 22:40 Comment(5)
The unit should be omitted on zero-lengths. On top of that, OP's code does have top: 0; defined for .child.Bigley
@Bigley w3.org/TR/CSS2/syndata.html#length-units The identifier is optional, so nothing wrong with adding it there and I personally think it's a whole lot clearer.Mailable
@Bigley The inline code wasn't there when I answered. He edited the question after I answered.Mailable
What could possibly be clearer than 0? Even though in fact you are correct and the unit is optional for zero-lengths, it's imo much more readable and concise than e.g. 0px. Btw, I think hardly anyone is referring to CSS 2 any more. This is the CSS 3 version of your link: w3.org/TR/css3-values/#lengthsBigley
@davidmulder thanks for answering. I did try the top property before posting the question on stackoverflow and found that setting top or not-setting was not making any difference. Not sure why you are saying that "top" is the issue here. (I have removed top again from the inline code). My question is why do I not need to set position of parent to "relative" in order to make sure that "absolute" of child work.Cynic

© 2022 - 2024 — McMap. All rights reserved.