duhan
Blog

z-index Hell

Recently, while working on a project, I saw that the elements I gave z-index were not placed correctly. I was constantly trying to change z-indexes between two elements and trying to look for a balance. Unfortunately, I didn’t succeed. Then I looked into it and found that there is such a thing as a stacking context.

Think of stacking context as like virtual borders between elements. Whenever you create an HTML element with certain CSS properties, you create a stacking context. From now on, children of this element cannot be compared to its siblings. There are multiple ways of creating a stacking context but most popular ones are:

  1. An element with a position value of absolute, relative, fixed, or sticky and a z-index value other than auto.
  2. An element with a transform value other than none.
  3. An element with an opacity value less than 1.

You can read from here for more: MDN

Let me give you an example:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <style>
      .parent {
        position: relative;
        z-index: 1;
        background: lightblue;
        width: 300px;
        height: 300px;
        transform: scale(1); /* New stacking context */
        display: flex;
        justify-content: center;
        align-items: center;
      }

      /* .child is shown behind the .sibling 
      because of the stacking context */
      .child {
        position: absolute;
        z-index: 999; 
        background: lightgreen;
        width: 150px;
        height: 150px;
        top: -20px;
        left: 70px;
        display: flex;
        justify-content: center;
        align-items: center;
      }
      .sibling {
        position: absolute;
        z-index: 2;
        background: coral;
        width: 100px;
        height: 100px;
        top: 0;
        left: 0;
        display: flex;
        justify-content: center;
        align-items: center;
      }
    </style>
    <title>Document</title>
  </head>
  <body>
    <div class="parent">
      Parent (z-index: 1)
      <div class="child">Child z-index: 999</div>
    </div>
    <div class="sibling">Sibling z-index: 2</div>
  </body>
</html>

In the above HTML document, the .parent element is creating a new stacking context for its children, but .sibling is not included in this context. So, .sibling and .parent can be compared to each other. This is a classic example of z-index.

However, the .child element is shown behind the .sibling even though its z-index is higher.

z-index hell