CSS negative z-index: what does it mean?
An element with a negative z-index will be rendered under most elements, unless they have an even lower z-index.
Does negative z-index have any side effects
Negative values are fine after Chrome 1.0, FireFox 3.0, IE 4.0, Opera 4.0, Safari 1.0. So basically if you don't live in 2000 you should be fine using negative z-indices. MDN doesn't seem to have any data for mobile devices though, but I would imagine since it's in the spec that most mobile browsers will also be fine.
Browser support of negative z-index values (CSS 2.1) according to the MDN
Why does the browser render the body behind elements with a negative z-index?
First, default z-index
is auto
and not 0
. There is a difference because the last one will create a stacking context making the element inside it (even with negative z-index
) to always be rendred above. More details here: Why can't an element with a z-index value cover its child?
Then you are facing background propagation which is a special behavior when setting background color to body element which will make you think that the element is not behind.
Then your image is set to position:absolute
making it out of the flow thus it won't affect the height of the body so even if it's behind we can still see it.
Here is some examples to illustrate different cases:
body {
position: relative;
background-color: #000;
}
img {
position: absolute;
z-index: -1;
top: 0;
left: 0;
width: 100%;
}
h1 {
margin: 0;
background-color: rgba(255, 255, 255);
padding: 0.5em 1em;
text-align: center;
font-size: 2.5rem;
}
<main>
<h1>A polar bear</h1>
<pre>
</pre>
</main>
<img src="https://upload.wikimedia.org/wikipedia/commons/3/3d/Polar_Bear_AdF.jpg" alt="A Polar Bear">
Why does negative z-index and non-static position disable my checkbox in most browsers?
The reason static
works is because z-index
is only applied to positioned elements - absolute
, relative
, fixed
.
I believe in this instance, IE may have got the z-index
right. The problem you are describing sounds like the checkbox
is being placed behind the parent element in Chrome, FF, Safari and Opera.
The following text extract from W3.org descibes the order in which the z-index elements are drawn:
Within each stacking context, the following layers are painted in back-to-front order:
the background and borders of the element forming the stacking context.
the child stacking contexts with negative stack levels (most negative first).
the in-flow, non-inline-level, non-positioned descendants.
the non-positioned floats.
the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks.
the child stacking contexts with stack level 0 and the positioned descendants with stack level 0.
the child stacking contexts with positive stack levels (least positive first).
However, it sounds like Chrome, FF, Safari and Opera could be drawing the negative z-index elements (2) before the parent element's background (1).
In any case, as you can see, the negative z-index
elements are pretty near the bottom of the pile, so if an element requires any kind of user interaction then a negative z-index
is probably not the best choice.
Additional Note
Another reason it could be working in IE and not the others is that IE tends to treat "empty" elements as if they do not exist. So if there is something drawn above the checkbox
but it contains nothing (no background, content etc) then IE will ignore it and allow interaction with the element below - where the other browsers will not.
Why can't an element with a z-index value cover its child?
There are two important things you need to know: the painting order and the stacking context. If you refer to the specification, you can find how and when elements are painted.
- Stacking contexts formed by positioned descendants with negative z-indices (excluding 0) in z-index order (most negative first) then tree order.
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.
- Stacking contexts formed by positioned descendants with z-indices greater than or equal to 1 in z-index order (smallest first) then tree order.
It's clear from this that we first paint elements with negative z-index
at step (3), then the one with z-index
equal to 0 at step (8), and finally the ones with positive z-index
at step (9), which is logical. We can also read in another part of the specification:
Each box belongs to one stacking context. Each box in a given stacking context has an integer stack level, which is its position on the z-axis relative to other boxes in the same stacking context. Boxes with greater stack levels are always formatted in front of boxes with lower stack levels. Boxes may have negative stack levels. Boxes with the same stack level in a stacking context are stacked bottom-to-top according to document tree order.
To understand when each element will be painted you need to know its stacking context and its stack level inside this stacking context (defined by z-index
). You also need to know whether that element establishes a stacking context. This is the tricky part, because setting z-index
will do this:
For a positioned box, the z-index property specifies:
- The stack level of the box in the current stacking context.
- Whether the box establishes a stacking context
Values have the following meanings:
<integer>
This integer is the stack level of the generated box in the current stacking context. The box also establishes a new stacking context.
auto
The stack level of the generated box in the current stacking context is 0. The box does not establish a new stacking context unless it is the root element.
Now we have all the information to better understand each case. If the parent element has a z-index
value of something other than auto
, then it will create a stacking context, thus the child element will be painted inside whatever their z-index
is (negative or positive). The z-index
of the child element will simply tell us the order of painting inside the parent element (this covers your second point).
Now, if only the child element has a positive z-index
and we set nothing on the parent element, then considering the painting order, the child will be painted later (in step (9)) and the parent in step (8). The only logical way to paint the parent above is to increase the z-index
, but doing this will make us fall into the previous case where the parent will establish a stacking context and the child element will belong to it.
There is no way to have the parent above a child element when setting a positive z-index
to the child. Also there is no way to have the parent above the child if we set a z-index
to the parent element different from auto
(either positive or negative).1
The only case where we can have a child below its parent is to set a negative z-index
on the child element and keep the parent at z-index: auto
, thus this one will not create a stacking context and following the painting order the child will be painted first.
In addition to z-index
, there are other properties that create a stacking context. In case you face an expected stacking order, you need to consider those properties, too, in order to see if there is a stacking context created.
Some important facts that we can conclude from the above:
- Stacking contexts can be contained in other stacking contexts, and together create a hierarchy of stacking contexts.
- Each stacking context is completely independent of its siblings: only descendant elements are considered when stacking is processed.
- Each stacking context is self-contained: after the element's contents are stacked, the whole element is considered in the stacking order of the parent stacking context. ref
1: there is some hacky ways if we consider the use of 3D transformation.
Example with an element going under its parent element even if this one has a z-index
specified.
.box {
position:relative;
z-index:0;
height:80px;
background:blue;
transform-style: preserve-3d; /* This is important */
}
.box > div {
margin:0 50px;
height:100px;
background:red;
z-index:-1; /* this will do nothing */
transform:translateZ(-1px); /* this will do the magic */
}
<div class="box">
<div></div>
</div>
css positioning z-index negative margins
z-index
is useless on a static positioned element. try position:relative
. if negative margins don't work out for you, use top
or bottom
and negative values.
Why does position:relative; appear to change the z-index?
You need to refer to the specification and more precisely the painting order to understand when each layer is painted.
Without position:relative
your element is not positioned and will be painted at the step (4):
- For all its in-flow, non-positioned, block-level descendants in tree
order: If the element is a block, list-item, or other block
equivalent:
Then we paint the positioned elements (including the .mask
) at the step (8)
- All positioned, opacity or transform descendants, in tree order that fall into the following categories
Now when you add position:relative
you make the container also positioned thus it will fall in the step (8) too and as described there we consider the tree order since both don't have any z-index
specified. So the .container
will painted later in this case.
If you change the order of the element (you make the container before the mask) you will notice that position:relative
won't have any effect because in both cases the painting order will be the same:
body {
margin: 0;
font-family: arial;
}
section {
position: relative;
background: url(https://preview.webpixels.io/boomerang-v3.6.1/assets/images/backgrounds/slider/img-41.jpg)
no-repeat left center/cover;
height: 70vh;
display: flex;
justify-content: center;
}
.container {
position: relative; /* you can remove this*/
width: 100%;
max-width: 1280px;
display: flex;
justify-content: center;
align-items: center;
color: white;
}
.mask {
position: absolute;
width: 100%;
height: 100%;
background: #3452ff;
opacity: 0.7;
}
<section>
<div class="container">
<h1>Hello World</h1>
</div>
<div class="mask"></div>
</section>
Related Topics
How to Do Ie Conditionals in CSS
Bikeshedding CSS3 Property Alternative
How to Make Bootstrap Responsive Design Work with Dotnetnuke
Alternative for Nth-Child for Older Ie Browsers
Vertically Align Bootstrap Badge Inside Heading
CSS Styling Won't Work in Outlook 2010
Table-Cell - Some Kind of Colspan
How to Use El for External CSS Files with Jsf
CSS Multiple Selectors Without Comma
Alternate Color Dot Over the Letter I
What Is the Purpose of CSS Prefixes
Why Do Chrome and Firefox Show Different Flex Layout Results
How to Display Image Over Image on Hover with CSS
Resizing Background-Image Always Proportionally to Scale with a Center Point