问题
can anyone explain how z-index default value works in this snippet
ul {
list-style-type: none;
padding: 0;
margin: 0;
width: 150px;
}
li {
position: relative;
}
li ul {
position: absolute;
background: green;
left: 20%;
border: 1px solid;
}
.foo {
background: red;
}
<ul >
<li>
<a href="">main element</a>
<ul class="first">
<li><a href="">First level</a>
<li><a href="">First level</a>
<li><a href="">First level</a>
<ul class="foo">
<li class="secound"><a href="">Secound Level</a></li>
<li class="secound"><a href="">Secound Level</a></li>
<li class="secound"><a href="">Secound Level</a></li>
<li class="secound"><a href="">Secound Level</a></li>
</ul>
</li>
<li><a href="">First level</a>
<li><a href="">First level</a>
<li><a href="">First level</a>
</ul>
</li>
</ul>
I expected sub ul to be on the top
but I don't know how text from top level wrapped over text from lower level ?
I can notice sub ul [red one] on the top and it can hide the top level border
So I expected that ul here working like container so every child element will follow it
I know If I give it z-index:1
will resolve it but I hope to understand the situation here if is possible
回答1:
It's all about paiting order. First let's add a top
value to better see what is happening:
ul {
list-style-type: none;
padding: 0;
margin: 0;
width: 150px;
}
li {
position: relative;
}
li ul {
position: absolute;
background: green;
left: 20%;
top:-20%;
border: 1px solid;
}
.foo {
background: red;
}
a {
font-size:20px;
color:#fff;
}
<ul >
<li>
<a href="">main element</a>
<ul class="first">
<li><a href="">First level</a>
<li><a href="">First level</a>
<li><a href="">First level</a>
<ul class="foo">
<li class="secound"><a href="">Secound Level</a></li>
<li class="secound"><a href="">Secound Level</a></li>
<li class="secound"><a href="">Secound Level</a></li>
<li class="secound"><a href="">Secound Level</a></li>
</ul>
</li>
<li><a href="">First level</a>
<li><a href="">First level</a>
<li><a href="">First level</a>
</ul>
</li>
</ul>
Note how the red element is above the first 3 elements and below the last 3 elements. If we check the specification related to the painting order we can read the following:
- All positioned, opacity or transform descendants, in tree order that fall into the following categories:
- All positioned descendants with 'z-index: auto' or 'z-index: 0', in tree order. For those with 'z-index: auto', treat the element as if it created a new stacking context, but any positioned descendants and descendants which actually create a new stacking context should be considered part of the parent stacking context, not this new one.
The main trick is here. All your elements are positionned and no one has z-index
specified so all will belong to the same stacking context and we will follow the tree order to paint them.
Following this logic we will have this order:
- the
ul
with classfirst
(the green box) - the first 3
li
insideul.first
- the
ul
with classfoo
(the red box) - all the
li
insideul.foo
- the last 3
li
insideul.first
Adding a z-index
will change the order and will also create some stacking context.
z-index:0
on ul.foo
will create a stacking context but will have no effect since we are already painting all the elements inside it right after it.
ul {
list-style-type: none;
padding: 0;
margin: 0;
width: 150px;
}
li {
position: relative;
}
li ul {
position: absolute;
background: green;
left: 20%;
top:-20%;
border: 1px solid;
}
.foo {
background: red;
z-index:0;
}
a {
font-size:20px;
color:#fff;
}
<ul >
<li>
<a href="">main element</a>
<ul class="first">
<li><a href="">First level</a>
<li><a href="">First level</a>
<li><a href="">First level</a>
<ul class="foo">
<li class="secound"><a href="">Secound Level</a></li>
<li class="secound"><a href="">Secound Level</a></li>
<li class="secound"><a href="">Secound Level</a></li>
<li class="secound"><a href="">Secound Level</a></li>
</ul>
</li>
<li><a href="">First level</a>
<li><a href="">First level</a>
<li><a href="">First level</a>
</ul>
</li>
</ul>
z-index > 0
on ul.foo
will move it to the top of everything since it will get painting at the step (9)
- Stacking contexts formed by positioned descendants with z-indices greater than or equal to 1 in z-index order (smallest first) then tree order.
ul {
list-style-type: none;
padding: 0;
margin: 0;
width: 150px;
}
li {
position: relative;
}
li ul {
position: absolute;
background: green;
left: 20%;
top:-20%;
border: 1px solid;
}
.foo {
background: red;
z-index:2;
}
a {
font-size:20px;
color:#fff;
}
<ul >
<li>
<a href="">main element</a>
<ul class="first">
<li><a href="">First level</a>
<li><a href="">First level</a>
<li><a href="">First level</a>
<ul class="foo">
<li class="secound"><a href="">Secound Level</a></li>
<li class="secound"><a href="">Secound Level</a></li>
<li class="secound"><a href="">Secound Level</a></li>
<li class="secound"><a href="">Secound Level</a></li>
</ul>
</li>
<li><a href="">First level</a>
<li><a href="">First level</a>
<li><a href="">First level</a>
</ul>
</li>
</ul>
z-index < 0
on ul.foo
will move it to the bottom of everything since it will get painting at the step (3)
- Stacking contexts formed by positioned descendants with negative z-indices (excluding 0) in z-index order (most negative first) then tree order.
ul {
list-style-type: none;
padding: 0;
margin: 0;
width: 150px;
}
li {
position: relative;
}
li ul {
position: absolute;
background: green;
left: 20%;
top:-20%;
border: 1px solid;
}
.foo {
background: red;
z-index:-2;
}
a {
font-size:20px;
color:#fff;
}
<ul >
<li>
<a href="">main element</a>
<ul class="first">
<li><a href="">First level</a>
<li><a href="">First level</a>
<li><a href="">First level</a>
<ul class="foo">
<li class="secound"><a href="">Secound Level</a></li>
<li class="secound"><a href="">Secound Level</a></li>
<li class="secound"><a href="">Secound Level</a></li>
<li class="secound"><a href="">Secound Level</a></li>
</ul>
</li>
<li><a href="">First level</a>
<li><a href="">First level</a>
<li><a href="">First level</a>
</ul>
</li>
</ul>
z-index < 0
on ul.foo
and z-index
different from auto
on ul.first
will first paint the green box then ul.foo
then all the li
inside ul.first
ul {
list-style-type: none;
padding: 0;
margin: 0;
width: 150px;
}
li {
position: relative;
}
li ul {
position: absolute;
background: green;
left: 20%;
top:-20%;
border: 1px solid;
z-index:0;
}
.foo {
background: red;
z-index:-2;
}
a {
font-size:20px;
color:#fff;
}
<ul >
<li>
<a href="">main element</a>
<ul class="first">
<li><a href="">First level</a>
<li><a href="">First level</a>
<li><a href="">First level</a>
<ul class="foo">
<li class="secound"><a href="">Secound Level</a></li>
<li class="secound"><a href="">Secound Level</a></li>
<li class="secound"><a href="">Secound Level</a></li>
<li class="secound"><a href="">Secound Level</a></li>
</ul>
</li>
<li><a href="">First level</a>
<li><a href="">First level</a>
<li><a href="">First level</a>
</ul>
</li>
</ul>
Related question to get more details:
Why can't an element with a z-index value cover its child?
来源:https://stackoverflow.com/questions/59550932/how-does-z-index-work-with-its-default-values