q126y
q126y

Reputation: 1671

Why setting absolutely positioned element's sibling as position:relative, brings it above the former?

HTML

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  <div class="c1">
    <div class="c2">
      <div class="circle">
      </div>
      <div class="c3">
        <div class="c4">    
        </div>
      </div>
    </div>
  </div>
</body>
</html>

If we change position of .c3 as position:relative, it is displayed on top of .circle, below the .circle, if we don't set position of .c3. Why does it happen?

Link to Jsbin

Edit: Clarified

Upvotes: 3

Views: 135

Answers (1)

Temani Afif
Temani Afif

Reputation: 272866

.c3 is placed after the .circle if the DOM so following the tree order .c3 is after .circle.

If both are positioned and there is no z-index specified so the .c3 will be placed above the .circle whatever the value of position is:

  1. With relative you will have this:

body {
  width: 500px;
  height: 500px;
}

.c1 {
  border: 1px solid blue;
  width: 90%;
  height: 90%;
}

.c2 {
  border: 1px solid green;
  width: 90%;
  height: 90%;
}

.c3 {
  border: 1px solid yellow;
  width: 90%;
  height: 90%;
  position: relative;
  background: blue;
}

.c4 {
  border: 1px solid red;
  width: 90%;
  height: 90%;
}

.circle {
  width: 100px;
  height: 100px;
  background: #f00;
  position: absolute;
  top: 200px;
  left: 350px;
  border-radius: 50%;
}
<div class="c1">
  <div class="c2">
    <div class="circle">
    </div>
    <div class="c3">
      <div class="c4">
      </div>
    </div>
  </div>
</div>

  1. With absolute you will have this:

body {
  width: 500px;
  height: 500px;
}

.c1 {
  border: 1px solid blue;
  width: 90%;
  height: 90%;
}

.c2 {
  border: 1px solid green;
  width: 90%;
  height: 90%;
}

.c3 {
  border: 1px solid yellow;
  width: 90%;
  height: 90%;
  position: absolute;
  background: blue;
}

.c4 {
  border: 1px solid red;
  width: 90%;
  height: 90%;
}

.circle {
  width: 100px;
  height: 100px;
  background: #f00;
  position: absolute;
  top: 200px;
  left: 350px;
  border-radius: 50%;
}
<div class="c1">
  <div class="c2">
    <div class="circle">
    </div>
    <div class="c3">
      <div class="c4">
      </div>
    </div>
  </div>
</div>

As you can read here:

  1. Stacking contexts formed by positioned descendants with negative z-indices (excluding 0) in z-index order (most negative first) then tree order.

...

  1. All positioned, opacity or transform descendants, in tree order that fall into the following categories:

    1. All positioned descendants with 'z-index: auto' or 'z-index: 0', in tree order. ...
  2. Stacking contexts formed by positioned descendants with z-indices greater than or equal to 1 in z-index order (smallest first) then tree order.

So we first consider z-index and if equal or not specified we consider tree order.


Now if .c3 is not positioned and we keep .circle positioned, the circle will go above .c3

body {
  width: 500px;
  height: 500px;
}

.c1 {
  border: 1px solid blue;
  width: 90%;
  height: 90%;
}

.c2 {
  border: 1px solid green;
  width: 90%;
  height: 90%;
}

.c3 {
  border: 1px solid yellow;
  width: 90%;
  height: 90%;
  background: blue;
}

.c4 {
  border: 1px solid red;
  width: 90%;
  height: 90%;
}

.circle {
  width: 100px;
  height: 100px;
  background: #f00;
  position: absolute;
  top: 200px;
  left: 350px;
  border-radius: 50%;
}
<div class="c1">
  <div class="c2">
    <div class="circle">
    </div>
    <div class="c3">
      <div class="c4">
      </div>
    </div>
  </div>
</div>

In this case we can read this:

  1. Stacking contexts formed by positioned descendants with negative z-indices (excluding 0) in z-index order (most negative first) then tree order.

  2. For all its in-flow, non-positioned, block-level descendants in tree order: If the element is a block, list-item, or other block equivalent:

In the (3) we consider positioned element with negative z-index and different from 0 (the .circle is not this case) so we don't print it yet and we print our in-flow element .c3 following (4). Then we will have this:

  1. All positioned, opacity or transform descendants, in tree order that fall into the following categories:
    1. All positioned descendants with 'z-index: auto' or 'z-index: 0', in tree order. ...

Now we print the .circle which explain why the circle is above the .c3 in this case.

If you specify a negative z-index to the circle it will fall in the (3) and thus it will be below .c3.

body {
  width: 500px;
  height: 500px;
}

.c1 {
  border: 1px solid blue;
  width: 90%;
  height: 90%;
}

.c2 {
  border: 1px solid green;
  width: 90%;
  height: 90%;
}

.c3 {
  border: 1px solid yellow;
  width: 90%;
  height: 90%;
  background: blue;
}

.c4 {
  border: 1px solid red;
  width: 90%;
  height: 90%;
}

.circle {
  width: 100px;
  height: 100px;
  background: #f00;
  position: absolute;
  z-index:-1;
  top: 200px;
  left: 350px;
  border-radius: 50%;
}
<div class="c1">
  <div class="c2">
    <div class="circle">
    </div>
    <div class="c3">
      <div class="c4">
      </div>
    </div>
  </div>
</div>

If you specify a positive z-index to .circle you will make it follow the (9) instead of the (8) and it will remain above:

body {
  width: 500px;
  height: 500px;
}

.c1 {
  border: 1px solid blue;
  width: 90%;
  height: 90%;
}

.c2 {
  border: 1px solid green;
  width: 90%;
  height: 90%;
}

.c3 {
  border: 1px solid yellow;
  width: 90%;
  height: 90%;
  background: blue;
}

.c4 {
  border: 1px solid red;
  width: 90%;
  height: 90%;
}

.circle {
  width: 100px;
  height: 100px;
  background: #f00;
  position: absolute;
  z-index:1;
  top: 200px;
  left: 350px;
  border-radius: 50%;
}
<div class="c1">
  <div class="c2">
    <div class="circle">
    </div>
    <div class="c3">
      <div class="c4">
      </div>
    </div>
  </div>
</div>

Upvotes: 3

Related Questions