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. ;-)
Related
I have an absolutely positioned div which is a child of a statically-positioned parent container. I'm finding that applying transform: translateY(-50%) to the container is causing the child to treat this container as though it were position: relative.
When I check absolutelyPositionedChild.offsetParent, it points to the container. And when I get container.computedStyleMap().get('position'), it gives me CSSKeywordValue {value: 'static'}. So it is most certainly static, and yet it's being used as the reference. The second I disable the transform in the dev tools inspector, the offsetParent changes to a much higher div that contains the whole app - as intended.
Is this documented somewhere or am I misunderstanding something? More pertinently, is there a way to force it to not be treated as the offsetParent?
According to the transform MDN,
If the [transform] property has a value different than none, a stacking context will be created. In that case, the element will act as a containing block for any position: fixed; or position: absolute; elements that it contains.
And according to the containing block MDN,
If the position property is static, relative, or sticky, the containing block is formed by the edge of the content box of the nearest ancestor element that is either a block container (such as an inline-block, block, or list-item element) or establishes a formatting context (such as a table container, flex container, grid container, or the block container itself).
So in this case, the parent element (a containing block that is statically-positioned) inherits the formatting context of the nearest block container. You will have an ancestor with position: relative that is cascading the formatting context.
To prevent this, you can make use of position: revert (though note that it won't work in Internet Explorer).
I was trying to reproduce this tutorial for a responsive menu. It all worked well, but I tried to keep the menu fixed on the top of the page for one of my projects. Unfortunately the hidden menu when fixed, do not change the z-index after the hover.
#icon_cont ul{
background-color: #cccccc;
margin-top: 75px;
z-index:-2; /**THIS DOES NOT APPLY**/
position: absolute;
top:100%;
padding: 0;
right: 0;
}
I tried in every way but it didn't work at all.
You can see in this example that when the container has relative position, it works, but when it's with the fixed position, the menu does not stay behind the other elements.
Appreciate, any help!
The reason is because you're applying postion: fixed; to the element. Fixing a position pushes to the front of the z-index stack. Here are the basic rules for understanding how the stacking order works:
The stacking context’s root element
Positioned elements (and their children) with negative z-index values (higher values are stacked in front of lower values; elements with the same value are stacked according to appearance in the HTML)
Non-positioned elements (ordered by appearance in the HTML)
Positioned elements (and their children) with a z-index value of auto (ordered by appearance in the HTML)
Positioned elements (and their children) with positive z-index values (higher values are stacked in front of lower values; elements with the same value are stacked according to appearance in the HTML)
(Taken from Philip Walton's invaluable post, "What No One Told You About Z-Index")
When you apply position: fixed; to an element, it sits in front of all relatively position items. Z-index values are relative to their "stack", not globally.
Every stacking context has a single HTML element as its root element. When a new stacking context is formed on an element, that stacking context confines all of its child elements to a particular place in the stacking order. That means that if an element is contained in a stacking context at the bottom of the stacking order, there is no way to get it to appear in front of another element in a different stacking context that is higher in the stacking order, even with a z-index of a billion!
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 <html> 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
(Emphasis mine)
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.
I have an<article> element inside a <div> and article has a position: relative;.
I moved it up 95px (bottom: 95px;) but the space it took up in its original place remained there. How can I make that disappear? When I do the same with article positioned as absolute, there is no problem. But I need to stick this to the middle too and margin: auto won't work with position:absolute.
http://jsfiddle.net/xnvMD/2/
I have an<article> element inside a <div> and article has a position: relative;.
I moved it up 95px (bottom: 95px;) but the space it took up in its original place remained there.
Well, this is how relative positioning is supposed to work – http://www.w3.org/TR/CSS21/visuren.html#choose-position:
“When a box B is relatively positioned, the position of the following box is calculated as though B were not offset.”
So the original space required by a relatively positioned element gets reserverd.
How can I make that disappear? When I do the same with article positioned as absolute, there is no problem. But I need to stick this to the middle too and margin: auto won't work with position:absolute.
Have you tried just using a negative margin-top to “move” the element upwards? This should work in all browsers (that are not from the stone age). And you can still set the horizontal margins to auto to have your element centered.
.trdown {
/* everything else besides position and bottom stays */
margin:-85px auto 0 auto;
}
(If this destroys the spacing at the bottom of the container element that you want to keep, then give that a padding-bottom as well.)
Instead of the relative position, use a negative top margin. Something like this:
margin:-95px auto 0 auto;
As CBroe has already pointed out, to get the arrow to show up over the image above, you'll need to add back the position:relative (but not the bottom) when you set the z-index.
position:relative;
z-index:1;
Technically you don't even need the z-index.
If you're curious why this works the way it does, you need to understand the rules for painting order in CSS. The full details are fairly complicated, but the basics are outlined in the section on the z-index property.
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).
By default, images (which classify as inline-level, non-positioned descendants) are at level 5, which is above your article element (a non-inline-level descendant) at level 3.
By adding a postion:relative to the article element, you've made it a positioned descendant, level 6, and thus moved it higher up the stack and above the image again.
Note that if your article had contained any inline content of its own, that would have displayed above the img element (they're both inline, but the article's inline content comes later in the tree order), but the article background and borders would still have painted below.
I dont have enough reputation to add a comment without first adding an answer. Without seeing code like Cody added it's difficult to help.
I think you're not entirely sure how positioning works. When an element is set to position: absolute, it's then positioned in relation to the first parent element it has that doesn't have position: static. If there's no such element, the element with position: absolute gets positioned relative to <html> (from Codecademy)
If you give an element relative positioning and tell it to have a margin-top of 10px, it doesn't move down ten pixels from any particular thing—it moves down ten pixels from where it otherwise would have been.
Remember, that if your using margin-auto on an element inside of another element, it will center inside of that element, as opposed to the document. Div's by default are the entire width of the page though.
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