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:
- An element with a position value of absolute, relative, fixed, or sticky and a z-index value other than auto.
- An element with a transform value other than none.
- 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.