4

I'm just learning the positioning in CSS. Based on the article that I've found useful, I'd started to playing around.

With the following code, I cannot understand why the absolute grey-box div is outside of it's relative parent. I expected that the grey-box will be on the top-left corner of the container.

.container { background: lightblue; position: relative; } .box-orange { background: orange; height: 100px; width: 100px; position: relative; top: 100px; left: 100px; z-index: 2; } .box-blue { background: lightskyblue; height: 100px; width: 100px; /*position: static;*/ } .box-green { background: lightgreen; height: 100px; width: 100px; position: relative; top: -105px; left: 105px; z-index: 2; } .box-grey { background: grey; height: 100px; width: 100px; position: absolute; }
<div class="container"> <div class="box-orange"></div> <div class="box-blue"></div> <div class="box-green"></div> <div class="box-grey"></div> </div>

Also can't understand in the following case why the grey-box not in the top-left corner, but moved after the empty space left by the orange-box there. I've just moved the grey-box to the second place inside the container div.

.container { background: lightblue; position: relative; } .box-orange { background: orange; height: 100px; width: 100px; position: relative; top: 100px; left: 100px; z-index: 2; } .box-blue { background: lightskyblue; height: 100px; width: 100px; /*position: static;*/ } .box-green { background: lightgreen; height: 100px; width: 100px; position: relative; top: -105px; left: 105px; z-index: 2; } .box-grey { background: grey; height: 100px; width: 100px; position: absolute; }
<div class="container"> <div class="box-orange"></div> <div class="box-grey"></div> <div class="box-blue"></div> <div class="box-green"></div> </div>

All the detailed documentation (e.g. MDN) and tutorials that I've found just demonstrating very simple examples with 2-3 boxes.

1
  • 3
    you didn't set any top/left .. set top/left to control the position or it will be positionned based on its static place. Since you are still learning no need to get confused about that default position Commented Feb 19, 2019 at 20:43

3 Answers 3

1

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>

Note the static position of the first element that is kept if we add position:absolute. We didn't specify any top value so the browser will use a default one that is the one of the position:static (default position) of the element.

If you don't want this, simply set the top value and you fall into this rule:

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

.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; top:0; } .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"></div> </div>

Same logic apply to the left property


You may also notice the use of the word containing block which very important here and explained in the same specification

The position and size of an element's box(es) are sometimes calculated relative to a certain rectangle, called the containing block of the element. The containing block of an element is defined as follows:

...

  1. If the element has 'position: absolute', the containing block is established by the nearest ancestor with a 'position' of 'absolute', 'relative' or 'fixed', in the following way:

...

And it's not enough as there is other properties (listed below) that also establish a containing block so you can have an element positionned relatively to an ancestor that is not positionned!

Related: Why does applying a CSS-Filter on the parent break the child positioning?

Sign up to request clarification or add additional context in comments.

Comments

1

You must always set top:0; left:0; on absolutely-positioned elements (or whatever values you want for top, right, bottom, left).

2 Comments

must always --> it's not a must, it will simply be easier
From the MDN >> The element is removed from the normal document flow, and no space is created for the element in the page layout. It is positioned relative to its closest positioned ancestor, if any; otherwise, it is placed relative to the initial containing block. Its final position is determined by the values of top, right, bottom, and left. This is what I cannot understand why I need to use the offsets
-1

First of all, the element is positioned relative to its first positioned (not static) ancestor element.

In this case, the position absolute works with the sibling, not with the ancestor.

About the ancestors and siblings, there are a godd documentation about it : Ancestors and siblings

.container { background: lightblue; position: relative; } .box-orange { background: orange; height: 100px; width: 100px; position: relative; top: 100px; left: 100px; z-index: 2; } .box-blue { background: lightskyblue; height: 100px; width: 100px; /*position: static;*/ } .box-green { background: lightgreen; height: 100px; width: 100px; position: relative; top: -105px; left: 105px; z-index: 2; } .box-grey { background: grey; height: 100px; width: 100px; position: absolute; }
<div class="container"> <div class="box-grey"></div> <div class="box-orange"></div> <div class="box-blue"></div> <div class="box-green"></div> </div>

If i put the element after the div container all works without problem

Documentation of postion

About the second part, that box appears there because the box-gery doesnt matter about the top and right of box-green, got it? Ill put an example:

.container { background: lightblue; position: relative; } .box-orange2 { background: orange; height: 100px; width: 100px; position: relative; z-index: 2; } .box-orange { background: orange; height: 100px; width: 100px; position: relative; top: 100px; left: 100px; z-index: 2; } .box-blue { background: lightskyblue; height: 100px; width: 100px; /*position: static;*/ } .box-green { background: lightgreen; height: 100px; width: 100px; position: relative; top: -105px; left: 105px; z-index: 2; } .box-grey { background: grey; height: 100px; width: 100px; position: absolute; } .box-yellow { background: yellow; height: 100px; width: 100px; position: absolute; }
<div class="container"> <div class="box-orange2"></div> <div class="box-grey"></div> <div class="box-orange"></div> <div class="box-yellow"></div> </div>

You can see that the grey and yellow boxes do not change the behavior even if the top and right are in the sibling or not.

12 Comments

Thanks a lot Alejandro I'd like to ask you regarding the first part that, you mentioned, as it was written in every documentation: the element is positioned relative to its first positioned (not static) ancestor element this means for me the container is the first positioned ancestor in this case. Why the grey-box is not positioned to its? Why it isn't in the top left corner of the container?
Hi, the ancestor of box-grey isn't container, it's box-green. box-green is postioned top: -105px; and left: 105px;, if you remove this propesrties you'll see that box-grey it's just under box-green. That's because the ancestor it's the element that is just before Regards
so but what you are saying is wrong, box-green isn't an ancestor of box-grey, it's a sibling element. The ancestor is not the before element
That's ture, srry. But, the propertie position works well with the siblings, so i supposed that the ancestor were in the top.
@MontyX no! he's not right. It's false. like I told you, you have to set top/left properties to see the desired result (top:0;left:0) .. and the ancestor is not the previous element
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.