notepadNinja
notepadNinja

Reputation: 488

Is content in absolutely positioned children considered part of the nearest aboslutely positioned ancestor?

consider the following simple code:

body {
  background-color: #990e82;
}

#header {
  background-color: #579900;
  position: absolute;
}

#inside {
  position: absolute;
  top: 0;
  left: 0;
}
<body>
  <div id="header">
    <div id="inside">hjhkjh</div>
  </div>
</body>

As it is possible to see in the attached snippet of the result, the outer div element's bg-color is not represented in the resulting page. Rather, the only color seen is the body's bg-color. I know the default height of block elements is determined by its content, and therefore it would seem that although the inner div element has text content, the inner div (being absolutely positioned) isn't actually considered part of the outer div element - a.k.a, the outer div has no content.

This surprises me, as the outer element is also positioned absolutely. As far as I know, this would make the outer div the containing block for the inner div for all intents and purposes (as defined in the spec - 10.1.4), and therefore "supply" the inner content to the outer div and stretch it. This would ostensibly result in the outer div's bg-color to show.

I would love for a clarification regarding the relationship between containing blocks, and the actual content contained in said blocks.

Upvotes: 1

Views: 47

Answers (1)

Temani Afif
Temani Afif

Reputation: 272582

As far as I know, this would make the outer div the containing block for the inner div for all intents and purposes (as defined in the spec - 10.1.4),

This is true, the containing block of inside is header

and therefore "supply" the inner content to the outer div and stretch it. This would ostensibly result in the outer div's bg-color to show

inside is also an inner content of header but it has position:absolute so it's out of the flow and doesn't affect the layout of it's containing block.

From the specification you can read:

In the absolute positioning model, a box is explicitly offset with respect to its containing block. It is removed from the normal flow entirely (it has no impact on later siblings). An absolutely positioned box establishes a new containing block for normal flow children and absolutely (but not fixed) positioned descendants. However, the contents of an absolutely positioned element do not flow around any other boxes. They may obscure the contents of another box (or be obscured themselves), depending on the stack levels of the overlapping boxes.

Then you can read here how width is calculated for absolute element and you will consider this rule:

If all three of 'left', 'width', and 'right' are 'auto': First set any 'auto' values for 'margin-left' and 'margin-right' to 0. Then, if the 'direction' property of the element establishing the static-position containing block is 'ltr' set 'left' to the static position and apply rule number three below; otherwise, set 'right' to the static position and apply rule number one below.

  1. ... then the width is shrink-to-fit. ...

Then you can see the detail of shrink-to-fit which is similar to inline-block, float, etc and since we have no in-flow content, it will result to 0 like you noticed.

Same logic for height calculation.


Basically, the containing block definition and how width/height are calculated are two different concepts. The containing block define a kind of reference for an element in order to place it or calculate its width/height but being a containing block of an element doesn't mean that the width/height will be different from 0.

Here is another intresting example where I will make the inside element width:100% and it will be equal to 0 because its containing block is having a width equal to 0 (our reference for calculation)

body {
  background-color: #990e82;
}

#header {
  background-color: #579900;
  position: absolute;
}

#inside {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  background: red;
}
<body>
  <div id="header">
    <div id="inside">hjhkjh</div>
  </div>
</body>

Upvotes: 2

Related Questions