What You May Not Know About the Z-index Property
By Steven Bradley
Translator: Chor
The z-index property looks simple on the surface, but if you want to understand how it works, there’s a lot to explore. This article will talk about the inner workings of Z-Index, starting with Stacking Contexts and some practical cases.
CSS provides three different positioning schemes for box model layouts:
-
Normal document flow
-
floating
-
positioning
The last option (specifically absolute positioning) would remove the element completely from the normal document flow, leaving its final destination up to the developer.
You can position an element in two dimensions by setting the values of top, left, bottom, and right, but CSS also allows you to place it in three dimensions using the Z-index property.
On the surface, z-index seems like a very simple property, where you set the value, the element will be located on the Y-axis, and that’s it. But it’s not as simple as you might think. Behind this attribute is a set of rules that determine the level of the element.
To make sure we’re on the same page, I’ll cover some of the basics, then explain cascading, and see how z-Index works in some scenarios.
Basic concepts of Z-index
You’re familiar with coordinates in three dimensions. The X axis represents the horizontal direction, the Y axis represents the vertical direction, and the Z axis represents the layout of the elements when we look at the page (screen).
Since the screen is a two-dimensional plane, we don’t actually see the Z-axis, more through perspective. Specifically, when multiple elements share the same two-dimensional plane, some elements are at the top and some are at the bottom, and we feel the z-axis.
To determine the position of an element along the Z-axis, CSS allows us to set three values for the z-index property:
-
Auto (default)
-
The integer
-
inherit
Let’s focus on integer values. It can be a positive integer, a negative integer, or 0, and the larger the value, the closer the element is to us, and the smaller the value, the further away the element naturally is.
If two elements share the same two-dimensional space after positioning, then in this space, the element with a larger Z-index may cover the element with a smaller Z-index.
Obviously, all of this is very easy to understand, and it’s intuitive. However, the following question may not be easy to answer:
-
When an element with positioning and z-index set overlaps with an element in a normal document flow, which one is at the top level?
-
One element is set to position, the other element is set to float, which one is at the top?
-
What happens if both parent and child elements are positioned?
To better understand these issues, it is necessary to understand some of the concepts related to how Z-index works, namely, cascading context, cascading hierarchy, and cascading order.
Cascade context and cascade level
It can be difficult to give a clear and understandable concept of cascading contexts and hierarchies, so we will use a simple example to understand it. Imagine that there is a table with all kinds of things on it. This table then represents a cascading context, and if there is another table next to it, another cascading context is created.
As shown in the figure, cascade context 1 refers to the document root, while cascade contexts 2 and 3 are in one of the cascade levels of 1. In addition, the two cascading contexts each contain a new cascade level.
Now imagine that there are four bricks side by side on the first table, and on top of those four bricks is a glass, and on top of that glass is a fruit bowl. So, the brick, the glass, the fruit bowl, each in a different hierarchy, but all in the hierarchical context of the table.
For each web page, a cascading context is created by default, and the root of the context (the table) is the HTML element, and all the children of the HTML element are placed at some level of cascading within the default cascading context, just as things are placed at different places on the table.
When you assign a non-auto Z-index to an element, a new cascading context is created that is independent of the other cascading contexts and hierarchies it contains, just as if you moved a new table into a room and it was independent of the old table.
Cascading order
We can understand the cascading order with a very simple example that doesn’t even involve positioning elements.
Imagine having a very simple web page that doesn’t take into account the default < HTML >, , , etc., and just needs to consider at least one
What do you think you’ll see when the page loads?
Of course, you don’t have to think too much about this, but you will definitely see a large blue, and there is a red block level element with a preset size. Unless you do something extra, this element will normally appear in the upper left corner.
You might say, “That’s it? Too simple “, but one question might not be so simple: why should a red block-level element be on top of a blue background? Why do we see div at the top of HTML? The reason is that they all follow the rules of cascading order.
In this simple example, by rule, the subblock (div) of a normal document flow will be higher than the background and border of the root element (HTML). We see div at the top because it has a higher level of hierarchy.
Although the above example only involves two levels of hierarchy, in fact, a total of seven levels of hierarchy can occur in a single hierarchy context, ranked from lowest to highest, as follows:
-
Background and border: The background and border of the element forming the cascading context, which is the lowest cascading level in the entire context.
-
Z-index negative: Sets the child element with z-index negative and the cascading context generated by it
-
Block-level box model: Block-level, non-located child elements in a normal document flow
-
Floating box model: Floating, non-positioned child elements
-
Inline box model: An inline, non-located child element in a normal document flow
-
Z-index is 0: The positioned child element with z-index set to 0 and the cascading context generated by it
-
Z-index is positive: The positioned child element with z-index set to positive and the cascading context generated by it, which is the highest cascading level in the entire context
These seven levels form the rules of the cascade order. An element that fits a cascade of levels seven is more “close to us” than an element that fits a cascade of levels one to six, an element that fits a cascade of levels five is more “close to us” than an element that fits a cascade of levels two, and so on.
The first time I learned these cascading rules, I felt like I was learning something new. If we just look at the cascading levels two, six, and seven (the z-index levels involved), then most of the time we get the Z-index right. A positive Z-index is higher than zero, and zero is higher than negative, which is all very intuitive, and probably most people don’t go any further at this point.
That’s what I did before, when I looked at these rules, and I thought that everything except positive and negative Z-indexes should be considered z-index 0 — but we know now that that was a mistake. The truth is that most elements have a level lower than z-index:0.
Another interesting detail is that the non-positioned elements are actually located in four different hierarchies. Strange at first thought, but it makes perfect sense. Given that all non-positioned elements are at the same level of hierarchy, we can’t see text (inline box) on div (block-level box).
Let’s look at an example
As I mentioned several times before, when you set z-inde to an element that is not Auto, a new, completely independent cascading context is created.
Go back to the table analogy. In the beginning, our table was covered with four bricks, with a glass on top and a fruit bowl on top. Now, suppose we have a new table with the same contents as the old one, except that the new table does not have a fruit bowl.
It’s not hard to imagine that the old table’s fruit bowl is the top item in the room (it has the largest Z-index), but what if the old table and everything on it were moved to the basement in its entirety? At this point, the fruit bowl will have a lower level than every item on the new table, because the old table on which the fruit bowl was placed is already lower than the new table.
The same is true for location elements on a web page. Given the following code, consider a question: div.two and div.four, which is on top and which is on bottom?
HTML:
<div class="one"> <div class="two"></div> <div class="three"></div> </div> <div class="four"></div>
Copy the code
CSS:
div { width: 200px; height: 200px; padding: 20px; } .one, .two, .three, .four { position: absolute; } .one { background: #f00; outline: 5px solid #000; top: 100px; left: 200px; z-index: 10; } .two { background: #0f0; outline: 5px solid #000; top: 50px; left: 75px; z-index: 100; } .three { background: #0ff; outline: 5px solid #000; top: 125px; left: 25px; z-index: 150; } .four { background: #00f; outline: 5px solid #ff0; top: 200px; left: 350px; z-index: 50; }
Copy the code
Although div.two has a higher Z-index (100), on the page it is actually lower than div.four (z-index 50). The following image shows the hierarchy of page elements. Based on the black and yellow borders, we can distinguish the different cascading contexts generated by each element.
Div. Two is located in div. One, so its z-index is dependent on the cascading context of div. One, i.e., the actual z-index representation looks like this:
-
. One — z-index = 10
-
.two —— z-index = 10.100
-
.three —— z-index = 10.150
-
.four —— z-index = 50
Div.one and everything contained within it will be hierarchically lower than div.four, and no matter how much z-index you set to a child element of div.one, the child element cannot be hierarchically higher than div.four.
Does this example have a familiar smell? I’ve been cheated by Z-Index once or twice. We’ve all wondered why an element with a very large Z-index can never be larger than an element with a much smaller Z-index on the hierarchy. I believe that after learning these cases, you have been suddenly enlightened.
conclusion
When we first learned about z-index, we all thought it was pretty simple, isn’t it just the position of the element on the Z-axis? But as we now know, there’s more to it than that. Understanding z-Index in depth also reveals some of the theoretical aspects behind z-index, including the cascading context, the cascading hierarchy, and the set of rules that determine the cascading order of elements.
Finally, it is important to remember that the positioning element creates a new cascading context in which all levels are higher or lower than all levels in another cascading context.
Develop reading
-
What No One Told You About Z-Index by Philip Walton
-
The Z-Index CSS Property: A Comprehensive Look on Smashing Magazine
-
How Well Do You Understand CSS Positioning?
-
The stacking context on Mozilla Developer Network
-
Z-Index And The CSS Stack: Which Element Displays First?