The original address

preface

Recently in the use of CSS3 animation encountered a DOM overlapping problem, so re-learn the Z-index, feel this CSS property is still quite complex, I hope this article can help you re-understand the charm of z-index.

Here’s what happened (the background is a bit long). I recently wrote the following list page:


Then add a CSS3 animation to each product item that looks something like this: Demo address

After the implementation of the effect is about like this (screenshots are a bit of paste, suggest point demo address view) :





It works fine in Chrome, but when you open it in Safari, it doesn’t.


It didn’t bother me when I was switching between different product items and found the page animation to be quite slow, so I added 3D animation hardware acceleration to each product item with a simple method like the following:

.item {
  transform: translateZ(0);      /* 或者 will-change: transform; */
}
Copy the code

This is a common way to optimize hardware acceleration, if you don’t understand this: use CSS to enable hardware acceleration to improve site performance

After opening Safari, I found that the page animation was smooth and the hardware-accelerated optimization was successful. However, a new problem emerged, namely the DOM element overlapping problem mentioned in this article.


Although the animation was fixed, there was a problem with page DOM element stacking: the following product item overwrote the entry box in the lower right corner of the product item, and we wanted the normal effect to look like this:


When I encountered such a problem, my first reaction was: I should have increased the z-index of the popbox, which was a piece of cake. However, no matter how I adjusted the z-index value, the popbox was always covered by the product items below. At first, I was puzzled.

Finally, I found a solution by reading some materials. Without further discussion, I will start to sort out the whole z-index related knowledge and submit the solution to the above problems in the end. (There are a lot of use cases that come with this tutorial. I’ve posted all of my code on JsFiddle for easy reference. You can click on the demo address to see the examples.)

Based on index z)

The z-index attribute is used to adjust the order of elements and their children on the Z-axis. When an element is overridden, which element is on top and which element is on the bottom. In general, elements with a higher z-index value overwrite elements with a lower z-index value.

Z – the index of the default value is auto, you can set the positive integer, also can be set to a negative integer, if we do not consider the CSS 3, only positioning elements (position: relative/absolute/fixed) z – index have a role, If your Z-index is applied to a non-positioned element (some CSS3 also works), it will not work. For example, demo address


When you position a DOM element, the element’s z-index takes effect. The default is auto. You can simply equate it to z-index: 0, for example, the demo address. In other words, z-index takes effect only when the location attribute (or some CSS3 attribute) is set.


After watching the demo, you may wonder why I only set the position property and not the Z-index value, and why the red square overwrites the blue square. This is where the z-index level comes in.

Stacking Level

A DOM element, without considering cascade context, can according to the cascade levels decision elements in the order shown on the z axis, easy to understand, different DOM elements together overlap, they display order will follow the rules of cascade levels and z – the index is used to adjust the display order of an element Allows the element to float up and down.

So what do cascading levels look like? Here are the famous 7 stacking levels


As you can see, the cascade level regulates the rendering rules for overlapping elements, and with this rule, it is not difficult to explain why the red square overlays the blue square in the previous example. Since the z-index: Auto element takes effect when you set position: relative, the level of stacking is higher than normal inline elements, so the red box is displayed at the top.

Now that I know the rules for cascading levels, here are a few examples:

An inline/inline-block element is higher than a floating element

The first is the inline/inline-block element above the floating element: the demo address


It is clear that the text (inline element) overwrites the image (float element).

The inline/inline-block element is higher than the block element

The demo address


The red square overwrites the green square, but since the text display:block is at the same level as the red square inline, following the come-frox-behind rule (explained next), Not overwritten by an inline-block element.

The elements overlap at the same level

When two elements are stacked at the same level, the following two rules should be followed:

  1. The late come-from-behind principle
  2. Who has the highest z-index, who is on top

The principle of come-from-behind:

The laggard rule states that when elements are stacked at the same level, the following DOM overwrites the previous DOM element. This is easy to understand, but too much to explain. This is why we often see the following element overwriting the previous one.

As we saw in the previous example, since the text (display:block) is inline level, the same as the red square, and follows the come-frod-behind rule (explained next), it is not overwritten by the inline-block element, I won’t post another example here.

Who has the highest Z-index and who is on top:

Due to the existence of Z-index, the order of elements in the same cascading context can be adjusted. Therefore, within the range of z-index negative and positive values, the larger the Z-index value of DOM elements in these two ranges, the higher the display order will be.

Once you know the level of the cascade, the order in which elements are displayed in the same cascade context is basically determined, but what about in different cascade contexts? What does this cascading context mean? Don’t worry. Keep reading.

Cascading context

A cascading context, which you can think of as a scope in JS, is often more than just one cascading context in a page (because there are many ways to generate a cascading context, you just don’t realize it). Within a cascading context, we stack elements at a cascading level.

After introducing the concept of cascading context, let’s first look at how to create a cascading context.

Normally, there are three major types of creating a cascading context:

  1. The cascading context is created by default
  2. You need to create a cascading context with the Z-index trigger
  3. You do not need to create a cascading context with z-index triggering

Create a cascading context by default

By default, the cascading context is created, with only the HTML root element, which you can think of as the body tag. It belongs to the root cascading context element and does not require any CSS attributes to trigger.

2. Create a cascading context with z-index trigger

Create a cascading context depending on the z-index value:

  1. Position value is relative/ Absolute /fixed(some browsers)
  2. Flex item (parent element display for flex | inline – flex), pay attention to is a child element, not the parent element to create cascading context

In both cases, the specific Z-index value must be set, but z-index cannot be set to auto, which is the slight difference between z-index: auto and z-index: 0.

As we mentioned earlier, setting position: relative to z-index to auto works, but it does not create a cascading context. If z-index is not auto, even if z-index: 0 is set, the element is triggered to create a cascading context.

No need to create a cascading context with z-index trigger

CSS3: CSS3: CSS3: CSS3: CSS3: CSS3

  • The opacity of an element is less than 1
  • The mix-blending-mode value of the element is not normal
  • The following attributes of the element have values other than None:
    • transform
    • filter
    • perspective
    • clip-path
    • mask / mask-image / mask-border
  • The isolution attribute value of the element is ISOLATE
  • The -webkit-overflow-scrolling attribute for the element is touch
  • The will-change attribute of the element has a value that creates a cascading context

After introducing the concept and how to create a cascading context, it is important to note that the element that creates the cascading context can understand the local cascading context. It only affects its descendants, and its own level of cascading is determined by its parent.

Compares the display order of two DOM elements

How do you compare the display order of two DOM elements?

  1. If in the same cascading context, display elements according to the rules of the cascading level
  2. If the context is different, first find the common ancestor and then compare the level of the local context in which the two elements reside under the common context.

A thousand words are condensed into these two sentences, but there are many points to pay attention to, let’s take the first point:

Common cascading context

If it is in the same context cascade, in accordance with the rules of cascading levels to display elements, before the cascade level was introduced in the introduction, it is worth noting that the father-son relationship elements is likely to be in the same context cascade, this case element hierarchy is also in accordance with the rules of cascading levels to show.

For example: the demo address


.box element and its child img: Because img and.box belong to the same cascading context, and because img z-index is -1, they sink below the parent element, which overwrites the image, but img is still above the background color of the body because it follows a 7-level cascade. The bottom must be the background or border of the cascading context (body element).

However, if we have the.box element create a local context, the.box element and the IMG element are also in the same context, but the context is switched to the local context created by.box.

The demo address


You will find: The img element overwrites the background color of the.box element because the background color of the cascading context is always the lowest. The cascading context changes from the body element to the.box element, but if the span element under.box is compared to the img element, Inline elements are higher than those with a negative z-index, so 2222 appears above the image.

The purpose of this example is to illustrate that the parent element may or may not be a local context, so we need to find a common context.

Different cascading contexts

This is more complex, can be summed up in a sentence: beating a dog depends on the owner, let me first draw a sketch to illustrate:


A typical DOM tree on a page might look something like this: Root, ParentX, and ChildX are all elements of a cascading context, not necessarily the parent of ABCD

  1. The element A wants to be compared with the element B or ChildB, happily, they belong to the same cascading context (ChildB), depending on the level of the cascade
  2. If an element A wants to be compared with C or ChildA, it looks for their common ancestor context (ParentB). Once it is found, it compares the level of the two elements according to their local context (ChildA and ChildB).
  3. Similarly, if A wants to have A showdown with D, just look for the ancestral cascading context (Root) and compare the cascading levels of ParentA and ParentB

Is it simple? Here are two simple examples to illustrate:

Example 1: Demo address


Although childA’s Z-index: 9999 is very large, but when comparing it with parentB or childB, it does not have the right to compare it. Only parentA can compare it with parentB. ChildA and parentA have no choice but to stay under parentB because your Z-index is 2.

If we change the example slightly so that parentA does not create a new cascading context element: the demo address


When parentA no longer creates a cascading context and childA wants to compare with childB, it is not restricted to parentA, but directly to parentB (because childA and parentB are in the same cascading context). Obviously childA is at the top, which is why childA overwrites parentB.

The solution to the problem

The theory is over, if you understand the above theory, this problem should be a piece of cake, here is the solution to the problem in the first place:

Because a transform is added to each product item: TranslateZ (0) creates a hierarchy context for each product item. According to the rule mentioned above, DOM elements in each product item are independent of each other, depending on each product item (each local hierarchy context), and because the hierarchy level of these product items is the same (as z-index: Auto), which follows the come-frod-behind rule, which results in subsequent elements overwriting previous ones. Take a simple example: the demo address


Just like that, even if you add a z-index attribute to the child, it doesn’t change the level of the cascade. The only way to do that is to change the Z-Index value of the item. Because we’re covering a special part, just the box part, and the box part is not displayed by default, It is only displayed when the mouse hover over the entry. The simplest way to do this is to increase the z-index value of an item when the mouse hover over it, destroying the last feature: the demo address

Final simplification effect:


Best practices

Speaking of this, it can actually end. In the process of learning, I watched the video recorded by Zhang Xinxu, and he proposed some best practices, which I think are quite good. Here is a brief introduction:

  1. Rule of two: For non-floating elements, avoid setting z-index values. There is no reason why z-index values should exceed 2
  2. For a floating element, you can get the maximum Z-index value of the body subelement by using JS, and then add 1 to that value as the z-index value of the floating element

For non-floating elements, do not use too much z-index to adjust the display order, but flexibly use the rules of cascading levels and come-from-behind to make the elements get the correct display. If you want to set z-index to adjust, it is not recommended that the z-index value of non-floating elements exceed 2. For DOM elements, -1, 0, 1, 2 is sufficient for elements to be displayed in the correct order.

For float elements, which are usually developed by third-party components, you can dynamically obtain the maximum z-index of all children of the body element on the page when you are not sure whether your float element will be 100% covered by the DOM tree. Add one to the z-index of the float element. Used to ensure that the float element is displayed at the top.

At the end

Finally, the z-index property has been finished, feel CSS properties have many eggs, next have time to contact more, more summary, have time to continue to share out.

Refer to the link

  • Z-index of CSS