Children of z-index: 'auto' vs z-index: 0, and what is "stacking context" in CSS? - html

Previously, I believed that a child element could not be z-indexed over an element that is a sibling of its parent element that has a higher z-index than its parent. For example, divs A and B are siblings. Div A has a z-index of 10, and div B has a z-index of 5. Div B has a child element: Div C, with a z-index of 9999. From my understanding, div C will not be positioned above div A, because div C's parent (div B) has a lower z-index than div A. This holds true, unless div B has a z-index of 'auto'. When div B has a z-index of 'auto', which would be '0', as it is inheriting from body, div C positions over div A, even though div B's z-index is actually LOWER than it was when it wasn't working.
From the CSS2 spec, z-index 'auto' is defined as
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.
I'm having trouble understanding "stacking context." It seems to be the only difference between a defined z-index of 0, and a default of 'auto' which is 0 but also has no stacking context. More specifically:
Why are children of elements with no stacking content z-indexed differently than those within a stacking context?
Here is a fiddle that shows the difference between z-index of 0, and a z-index of auto. The green div is a child of the blue div, and the red div is a sibling of the blue div.
http://jsfiddle.net/c7Tvt/

In your example, you have two scenarios, call them Blue and Blue-2.
In Blue, you have two stacking contexts, the first contains #blue and the second contains #red and #green. #blue is in its own stacking context because z-index: auto, and this context is simply part of the default stack.
In Blue-2, you have defined z-index: 0 for #blue, so it is part of the same stacking context as #red. In Blue-2, #blue is painted first because it has the lowest z-index, 0. However, #green is a child of #blue and gets painted over #blue, the parent and child form a new stacking context (a sub-stacking context if you wish).
Finally, #red is painted over the blue-green stack because the red z-index is 2, which is greater than the blue z-index of 0. In this case, the z-index of green affects its stacking level with respect to blue and any other child elements in #blue. In Blue-2, there are three stacking contexts, the default (#1), the one for red and blue (#2), and the other that is blue and green (#3).
Key Point
z-index: auto does not start add a positioned element to a new stacking context whereas z-index: 0 does. Remember, there is at least one stacking context, the default one that is defined for the elements by virtue of their natural HTML/DOM order on the page.
Note: I took the liberty of describing the staking position as if you had two web pages, one with #red, #blue, #green and the second with #red2, #blue2, #green2. In reality, since all the div's are on the same page, all the stacking levels contain all the elements. When there are two red div's in the same stack, #red2 would be painted over #red since elements further down the DOM tree are painted over earlier elements.
Reference
I found the following quite useful to read:
https://developer.mozilla.org/en-US/docs/CSS/Understanding_z-index/Stacking_context_example_2
If you want even more detail, try looking at:
http://www.w3.org/TR/CSS21/zindex.html

Related

`will-change: opacity` doesn't create new stacking context

in MDN web docs it is mentioned that stacking context is formed in these scenarios:
Element with a opacity value less than 1
Element with a will-change value specifying any property that would create a stacking context on non-initial value
but when I set will-change to opacity (non-initial value of less than 1) the stacking doesn't work as expected (blue div below red one), see this fiddle
some other scenarios works as expected like; blue div above red one (links to fiddles)
Element with a position value absolute or relative and z-index value other than auto
Element that is a child of a grid container, with z-index value other than auto
what am I doing wrong, and is there any other way to make stacking context works as expected
I'm asking because sometime I can't change the position to relative as this will affect the absolute children of that element
The stacking (creation of a new layer) is actually working.
The problem is that z-index works only for:
Positioned elements (absolute, relative, fixed, sticky).
Children elements of a flex container.
No matter if you set z-index: 30, at the end it will remain at its default value, auto.

With no z-index, why does an early sibling covers up a later sibling in DOM?

I have a simple page with 3 DIV's: http://jsfiddle.net/AxX29/32/
With the HTML:
<div id="content1">foo</div>
<div id="overlay"></div>
<div id="content2">bar</div>
and CSS:
#overlay { width: 160px; height: 160px; background:yellow;
position: absolute; top:0; left: 0 }
I thought that when no element has any z-index defined, that means they are all auto (as shown by the JS in the jsfiddle), so that means the effective z-index is 0, and they would appear in the order of the DOM tree traversal (probably depth first search), meaning that overlay should cover up content1, while content2 should cover up overlay, but as it turns out, overlay covers up both content1 and content2, why is that?
(I know I can put a z-index of -1 to overlay and make it go below content1 and content2, but the question is, if no z-index is given, why does overlay cover up both content1 and content2?)
Giving an element position: absolute; removes it from the normal document flow and puts it on top of other elements.
You can add position: relative; to a parent div to make the absolute-positioned element positioned absolutely relative to the parent, rather than absolutely relative to the entire document.
EDIT: As you mentioned that you know already, applying z-index to positioned elements will change their depth behavior (the stacking context, as it's technically called); applying z-index: 100; position: absolute; to your first element, for example, would put it above the position: absolute; element.
From the CSS spec:
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).
Here is my attempt at it, auto just means default.
The only thing to infer is that by choosing a position:relative/absolute/static etc. you are enabling an element to fall in to the domain of z-indexing. While it is effectively at position 0, it has more weight than a inline positioned element.
So index -1 places underneath the inline elements and index 0 or 1 does nothing.
I guess the answer is that auto/baseline is index 0, any elements with no position: (inline elements) live in plane 0 but have an inactive zindex. Any absolute element will overlay an inline positioned element zindexed or not.
Also worth noting is, if you absolutely position all three elements, they all overlay each other in the reverse order that they are in the DOM (last on top, first on bottom). which means the z-index weighting seems to favour the last element in the DOM.

HTML, CSS, z-index

I can't understand something with z-index, If you take a look at this fiddle you may see that there is an hidden span behind the div.
I have learned that all the elements hasz-index: 'auto'; which says that they inherit the z-index from their parents, the only element that has z-index is the html element with z-index: 0;, so if what I just told is true all the elements(with position absolute, fixed, relative) by default should have z-index: 'auto'; which is basically z-index: 0;.
Now if you take a look at this fiddle I set z-index: 0; for the div element and to my surprise the span is no longer hidden, I'm surprised because the default z-index for the div should be 0 and the div should hide the span.
So my question is why when I set the z-index: 0; for the div element the span is no longer hidden, I mean the span should stay hide no?
Hope this will do some help.
The Default Value: auto
The specification has this to say about the default value,auto:
The stack level of the generated box in the current stacking context is the same as its parent's box.The box does not establish a new local stacking context.(CSS2.1:9.9.1)
That means: you can treat any element with z-index:auto as z-index:0.But the difference is z-index:autowon't establish a stacking context,but the latter does.
You may understand the phrase 'stacking context' as the new containing blocks established by the element whose z-index is not auto.
To see your problem specifically:
1)span{z-index:-1} & no explicit z-index for div,actually right now the div{z-index:auto}
Given the rules of stacking,the div won't establish a new stacking context,so its child is placed in the same stacking context as the body element.In other words, the span is behind the body element.
2)span{z-index:-1} & div{z-index:0;}
In this situation, the span is part of the stacking context established by the div , not the initial containing block's stacking context any more.Remember this.
So, the span will never be stacked below the background of its stacking context ,just as your second fiddle shows.
P.S. The stacking rules are not like this until CSS2.1. ;-)

I need to put in lower level an object

i have made a scrolling manu and when I try to select it the list of the menu goes behind of an object (a simple music player). How can i put that object in lower level? I know I should use z-index command but i don't know the value. I tried them all.
z-index:0;
z-index:1;
z-index:auto;
Whatelse can I use?
It's worth noting that z-index is only obeyed on positioned elements (absolute, relative, or fixed). If you put a z-index on a non-positioned (static) element, it will be ignored.
The value of z-index is any integer or auto;
z-index only works on explicitly positioned elements with a position of absolute, relative or fixed.
additionally, their 'stacking context' is relative to their position in the DOM. two sibling elements are in the same stacking context, but their children elements are in a new stacking context (so if you have two sibling parents with z-index: 1, and one of them has an immediate child with z-index: 1 and the other has an immediate child with z-index: 2, the latter will have the higher z-index because its stacking context is 1-2 versus 1-1. However if for example you have two parent sibling elements where one has a higher z-index than the other, no descendant of the parent with the lower z-index will ever have a higher z-index than children of the parent with the higher z-index, even if you set the former's children to z-index: 500 or something like that. Basically stacking contexts exist at each level of the DOM and their effects cascade to all of the lower stacking contexts generated by their descendants.
z-index is tricky to master and requires a lot of attention to the markup and DOM structure. you need to post all of the relevant CSS and HTML in order for us to help you.
You can read some more about z-index on Mozilla Developer Network

CSS3 z-index issue

Sorry for such a "dummy" question but I really couldn't find a solution.
I have illustrated the situation graphically:
Inside the container, there are TWO siblings (RED <div>and BLUE <div>). Both have position: absolute;
RED has z-index:1;
BLUE has z-index:2;
RED's child (GREEN) has position:relative; and z-index:99;
I want to make GREEN to be upper than BLUE
Thank you!
UPDATE 1. Here is the fiddle
http://jsfiddle.net/yn9z7/
The key to solve that is in the article linked by sudhAnsu63 :
New stacking contexts can be formed on an element in one of three ways:
When an element is the root element of a document (the element)
When an element has a position value other than static and a z-index value other than auto
When an element has an opacity value less than 1
But the interpretation is just the opposite. To set the blue element between the red and the green, the red one can not generate a stacking context. It is generating an stacking context because of the second rule; it has position absolute an z-index different from auto.
So, the solution is:
#red{
z-index:auto;
}
demo
This won't work since Red's z-index is lower than blue. z-index only works with elements with a common root element.
Check out the Stacking Contexts part in this article
Here the Blue div and the Red div is the direct child of container div. z-Index will not work exactly.
try changing the opacity of blue div to 0.99;
.bluediv {
opacity: .99;
}
http://philipwalton.com/articles/what-no-one-told-you-about-z-index/
http://coding.smashingmagazine.com/2009/09/15/the-z-index-css-property-a-comprehensive-look/
yeah, this is not possible because child elements inherit the z-index of the parent. so it does not make sense to give the green div a z-index of 99 because it's z-index is only valid inside the parent (red div).
So if you give a container a certain z-index lets say 20, the z-indexing inside this container starts again from 0. this is a good thing because otherwise we had to give all children a z-index of minimal 21 or they won't be visible.
the first container on a web page is the body tag, you can stack all its children with the z-index property starting from layer 0 (z-index 0). just like the body tag every child has its own z-index "system" unrelated to higher elements in the DOM. so the z-indexing starts over from 0 inside a parent container with its own defined z-index.