How Position Absolute and Fixed Block Elements Get Their Dimension

How position absolute and fixed block elements get their dimension?

Here is the Specification detailing how you can find the width/height of any element: https://www.w3.org/TR/CSS21/visudet.html

From there you can read for absolute element that:

The constraint that determines the used values for these elements is:

'left' + 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' + 'right' = width of containing block

Then

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.

And the rule number three:

'width' and 'right' are 'auto' and 'left' is not 'auto', then the width is shrink-to-fit . Then solve for 'right'

The rule number one is also similar

And if you continue reading you will find how to calculate the shrink-to-fit width. You will also notice that the same shrink-to-fit algorithm apply to float and inline-block element


Also note that fixed element is a particular case of absolute so the same rule applies. The only difference is the containing block

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. ref


You can also see that block elements follow almost the same constraint (without left/right) but the rules are different:

The following constraints must hold among the used values of the other properties:

'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = width of containing block

Then

If 'width' is set to 'auto', any other 'auto' values become '0' and 'width' follows from the resulting equality.

This will make width = width of containing block


An important difference between inline-block element is that absolute element will not take the width of their content like we may think. This happen in most of the case due to the constraint explained above but check the below example:

.container {
clear:left;
margin:5px;
}
<div class="container" style="float:left;position:relative;">
<div style="display:inline-block; background: red;"> 1 1 1 1 1 1 </div>
</div>

<div class="container" style="float:left;position:relative;">
<div style="position: absolute; background: red;"> 1 1 1 1 1 1 </div>
</div>

Do fixed and absolutely positioned elements not take the full width of their container like block elements? If yes then why?

This question could have different possible answers depending on what kind of block behavior you're expecting or referring to.

As per your comment above, the following answer refers to the width behaviour of such element.

Normally, block-level elements per default take up the full available width of their container element. However, when you set position: fixed or absolute the element isn't displayed in the same sense as with the rest of the elements.

As per MDN:

A block-level element occupies the entire space of its parent element (container), thereby creating a "block."

As such, the meaning of the container for a block-level element makes alters when refering to absolute or fixed positioned elements. It makes more sense to rather call it the parent.

Since there is no container element to inherit its width, you're seeing it behave more like an inline-block-type element.

Here's what the W3C says for calculating the width of an absolutely positioned, non-replaced element:

The constraint that determines the used values for these elements is:

left + margin-left + border-left-width + padding-left + width + padding-right + border-right-width + margin-right + right = width of containing block.

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;

This is true. You have not defined any values for width, left nor right nor do they inherit such values. As such they take the default auto. The direction property is indeed ltr as well, so we continue on to rule number three as suggested, which says:


  1. width and right are auto and left is not auto, then the width is shrink-to-fit . Then solve for right.

The shrink-to-fit width rule applies, and goes as follows:

Calculation of the shrink-to-fit width is similar to calculating the width of a table cell using the automatic table layout algorithm. Roughly: calculate the preferred width by formatting the content without breaking lines other than where explicit line breaks occur, and also calculate the preferred minimum width, e.g., by trying all possible line breaks. CSS 2.1 does not define the exact algorithm. Thirdly, calculate the available width: this is found by solving for width after setting left (in case 1) or right (in case 3) to 0.

Then the shrink-to-fit width is: min(max(preferred minimum width, available width), preferred width).

Why are fixed and absolute positioned elements considered block formatting context, but not a relatively positioned elements?

I would say because position:relative doesn't change the behavior of the element like absolute and fixed will do. When setting an element with absolute and fixed, it will get removed from the flow. It's like you remove a fragment of the page to make it independent thus it need to establish a new block formatting contexts.

Whith position:relative it's different.

Once a box has been laid out according to the normal flow or floated, it may be shifted relative to this position. This is called relative positioning.

then

A relatively positioned box keeps its normal flow size, including line breaks and the space originally reserved for it.ref

Basically, position:relative will keep the behavior of the element and will simply allow you to shift its position after being placed in the normal flow. You need to check the other properpties to see if the element will establish a BFC or not.

You may also note that positon:relative apply to inline element and inline element should not establish a BFC.

Does position absolute make that element a containing block?

We establish that #strong1 is a non-positioned inline box. Therefore, from the spec,

[...] if the element's position is 'relative' or 'static', the containing block is formed by the content edge of the nearest block container ancestor box.

When #em1 is not absolutely positioned, it remains an inline box. The nearest block container ancestor box to #strong1 is #p2, therefore #p2 is its containing block.

When #em1 is absolutely positioned, it turns into a block box as shown in section 9.7. This makes it the nearest block container ancestor box to #strong1, therefore #em1 becomes its containing block. A block box is defined as a block-level block container box.

So does absolute positioning cause an element to establish a containing block for relatively positioned or non-positioned boxes? Yes, but only when absolute positioning results in the element's box becoming the nearest block container ancestor of those boxes.


Note that this is a rather simplified case, since the only boxes in #em1 are inline boxes (including the two anonymous inlines surrounding #strong1). Besides the fact that not all block-level boxes are block containers (tables being a common example of a block-level box that's not a block container box), even if absolute positioning does result in an element generating a block box, since we're talking about an inline box here, it may very well be that the inline box's block container is an anonymous block box within the absolutely positioned element, if that element happens to contain a mix of both block-level and inline-level boxes. This complicated case is detailed in section 9.2.1.1.

But the complications don't stop there. The reason I say "it may very well be" is because whether or not an anonymous block box is capable of establishing a containing block isn't defined in CSS2.1.



Related Topics



Leave a reply



Submit