Lecture
The problem with z-index is that few people clearly understand how it actually works. There is nothing difficult in it, but if you have never devoted time to reading its specification, you will almost certainly not be aware of important aspects.
Do not believe me? See if you can solve the following problem.
In the HTML below, we have three <div> elements, each of which contains a <span> element. Each element, in turn, has a background color of red, green, and blue, respectively. Also, each <span> element has absolute positioning somewhere near the upper left corner of the document and slightly overlaps the other <span> elements so that it can be seen which element is on top of the other. For the first <span> element, the value of the z-index property is 1, and for the other two, this property is not set.
Here’s what the HTML and basic CSS styles look like. Below, I also added a visual demo with Codepen with full CSS.
|
1
2
3
4
5
6
7
8
9
|
<div>
<span class="red">Red</span>
</div>
<div>
<span class="green">Green</span>
</div>
<div>
<span class="blue">Blue</span>
</div>
|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
.red, .green, .blue {
position: absolute;
}
.red {
background: red;
z-index: 1;
}
.green {
background: green;
}
.blue {
background: blue;
}
|

The challenge is as follows : try to position the red <span> element behind the blue and green elements, without violating the following conditions:
z-index property of elements position property of elements You should get the following picture:
Attention! Do not click on the tab with CSS, so as not to spy on the answer.
The answer is to add opacity to the first <div> element (the parent of the red <span> element) with a value slightly less than 1. Here is the CSS that was added to the example above:
|
1
2
3
|
div:first-child {
opacity: .99;
}
|
If you are now in shock, puzzled and can not believe that transparency will affect the order of blending elements, welcome to the club. I was just as shocked when I first came across this situation.
I hope the rest of this article will clarify the situation a bit.
Z-index seems so simple: elements with a higher value should be above elements with a lower value, right? Not really. This is part of the problem with z-index . At first glance, it seems simple and most developers do not spend time studying the rules for its use.
Each element in an HTML document can be located either above or below other elements. This is called the overlay order. The rules of this overlay are quite clearly defined in the specification, but, as I said, most developers do not fully understand them.
When the z-index and position properties are not defined, the rules are very simple: the overlay order is exactly the same as the order of appearance in HTML, basically. (OK, in fact, everything is a bit more complicated, but as long as you do not use the negative values of the margin property to overlap the line elements, you most likely will not encounter extreme cases).
If we talk about the position property, then any positioned elements (and their descendants) are displayed above any non-positioned elements. (Speaking of a “positioned” element, it means that an element has a position property other than static — relative , absolute or fixed .)
And finally, if the z-index property is involved, then everything becomes a bit more complicated. We assume that items with a higher z-index value are above the items that have a lower z-index value, and also any items that have a z-index value set are above the items without a z-index . But everything is not so simple. First of all, z-index works only on positioned elements. If you try to set the z-index property to an element without positioning, nothing will happen. Second, the values of the z-index property can create overlay contexts. Now, what seemed simple at the beginning has become more difficult.
Groups of elements with a common parent, which together move up and down in the overlay order, create what is called an overlay context. A complete understanding of the context of the overlay is the key to understanding how the z-index and the overlay order work.
As a root element, each context overlay has one HTML element. When a new overlay context is formed on an element, this overlay context encloses all its child elements in a specific place in the overlay order. This means that if an element is contained in an overlay context below an overlay order, there is no way to force it above another element with a different overlay context that is higher in the overlay order, even if you set the z-index to a billion!
New overlay contexts can be formed on an element in one of three cases:
<html> element) position property value other than static , and a z-index property value other than auto opacity value less than one The first and second instances of the formation of the context overlay make sense and, as a rule, are understood by web developers (even if they do not know what they are called).
The third case (opacity) is almost never mentioned outside of the W3C specification documents.
In fact, defining the global order of overlapping all elements on a page (including borders, backgrounds, text nodes, etc.) is extremely difficult and goes far beyond the scope of this article (again, I refer you to the specifications).
But for most tasks and goals, a general idea of the order can go far and help keep CSS development predictable. Let's start by disrupting order in individual overlay contexts.
Overlay order within the same overlay context
Here are the basic rules to determine the order of the overlay in one overlay context (from bottom to top):
z-index property (larger values “fit” above smaller values; elements with the same values are arranged in the same order as in HTML) auto value of the z-index property (arranged in the same order as in HTML) z-index property (larger values “fit” above smaller values; elements with the same values are arranged in the same order as in HTML) Note: Positioned items with negative
z-indexvalues will be placed first in the context of an overlay, which means that they will be displayed behind all other items. Because of this, the element has the opportunity to be behind its parent, which is usually impossible. This will only work if the parent of the element has the same context overlay and is not its root element.
Having a clear understanding of how / when new overlay contexts are formed, as well as an idea of the overlay order in the overlay context, finding out where a particular element will appear in the global overlay order is not so difficult.
The key to not stumble on this path is the ability to determine when new contexts overlay are formed. If you set the element to z-index at a billion and it does not move higher in the overlay order, look at its family tree to see if any of its parents form the context of the overlay. If formed, then your z-index in a billion will not give any benefit.
Returning to the original task, I recreated its HTML structure by adding comments inside each tag that indicate its place in the overlay order. This is the order of the original CSS rules.
|
1
2
3
4
5
6
7
8
9
|
<div><!-- 1 -->
<span class="red"><!-- 6 --></span>
</div>
<div><!-- 2 -->
<span class="green"><!-- 4 --><span>
</div>
<div><!-- 3 -->
<span class="blue"><!-- 5 --></span>
</div>
|
When we add the opacity rule to the first <div> element, the blending order changes:
|
1
2
3
4
5
6
7
8
9
|
<div><!-- 1 -->
<span class="red"><!-- 1.1 --></span>
</div>
<div><!-- 2 -->
<span class="green"><!-- 4 --><span>
</div>
<div><!-- 3 -->
<span class="blue"><!-- 5 --></span>
</div>
|
span.red was 6, and became 1.1. I used a dot to show that a new overlay context has formed and span.red now the first element in the new context.
I hope that you now understand why the red block was behind all the others. The original example contained only two overlay contexts, the root and another, formed by the span.red element. By adding the opacity to the parent of the span.red element, we created a third overlay context and, as a result, the z-index value of the span.red element now operates within the context of the new context. Due to the fact that the first <div> element (the one to which we applied opacity) and its related elements are not positioned and do not have the z-index property set, their order of blending is determined by the order in HTML, which means that the first element <div> and all elements in its context overlay are located behind the second and third <div> elements.
Comments
To leave a comment
Cascading CSS / CSS3 Style Sheets
Terms: Cascading CSS / CSS3 Style Sheets