I have a code like this (divs have absolute positions and overlap each other at least partially):
<div style="z-index: 1">
<div style="z-index: 3">
</div>
</div>
<div style="z-index: 2">
<div style="z-index: 4">
</div>
</div>
It seems to work okay in the browsers I need, but somehow it doesn't feel right. So my question is: should I consider another approach or this technique is completely legit?
In CSS, z-index values are relative to stacking contexts, which do somewhat rely on hierarchy.
As all your divs are absolutely positioned and have a z-index that is not auto, every one of them establishes a stacking context for their descendants. So the first inner div participates in the first outer div's stacking context, and its z-index is relative to that stacking context. Likewise, the second inner div participates in the second outer div's stacking context, and its z-index is relative to that stacking context.
Because they are confined to their own parent stacking contexts, neither of the two inner divs is aware of the other. In other words, whatever z-index you set to one inner div will never have an effect on the other.
However, assuming everything else is defaulted, the two outer divs participate in the same parent stacking context, so the second can be said to have a higher z-index (or higher stack level) than the first, and swapping their z-index values will indeed cause the one with the higher stack level to then appear in front of the one with the lower stack level.
All of this is defined clearly in section 9.9 of CSS2.1, and can be relied on, bugs notwithstanding.
Related
I am a little confused about using z-index to decide stack order.
I do not quite understand how browsers treat elements with the position property in conjunction to those without it.
Is there a general rule to decide the stack order of elements whether it has explicitly positioned elements or not?
Examples of different situations are appreciated. Generally speaking:
mixed sibling <div>s with position set and without position set.
nested <div>s mixed with sibling <div>s with position set and without position set.
Basics of the CSS z-index property
A Simple Concept
The z-index property is based on a simple concept: Elements with higher values will sit in front of elements with lower values along the z-axis. So if you apply z-index: 1 to div.box1, and div.box2 has a z-index: 0, then div.box1 will overlay div.box2.
In terms of the z-axis, it refers to depth on a three-dimensional plane. On your computer it can be interpreted as the plane on which objects move closer and farther from you. (Learn more about the Cartesian coordinate system.)
Source: Wikipedia
z-index works on positioned elements
Unless you're dealing with flex items or grid items, the z-index property works only on positioned elements. This means you can use z-index on elements with position: absolute, position: relative, position: fixed or position: sticky. If the element has position: static (the default value), or some other positioning scheme like a float, then z-index will have no effect.
As noted, although z-index, as defined in CSS 2.1, applies only to positioned elements, flex items and grid items can create a stacking context even when position is static.
4.3. Flex Item Z-Ordering
Flex items paint exactly the same as inline blocks, except that order-modified document order is used in place of raw
document order, and z-index values other than auto create a stacking context even if position is static.
5.4. Z-axis Ordering: the z-index property
The painting order of grid items is exactly the same as inline blocks, except that order-modified document order is
used in place of raw document order, and z-index values other than auto create a stacking context even if
position is static.
Here's a demonstration of z-index working on non-positioned flex items: https://jsfiddle.net/m0wddwxs/
Stacking Contexts
Once an element is positioned and a z-index is applied, a stacking context is created.
(Also see: Full list of circumstances where a stacking context is created.)
The stacking context is a set of rules for managing the positioned element with z-index, and its descendants. These rules govern the placement of child elements in the stacking order and the scope of the property's influence.
Essentially, the stacking context limits the z-index scope to the element itself, and its child elements cannot affect the stacking order of elements in another stacking context.
If you've ever tried to apply increasingly higher z-index values only to find that the element never moves out in front, you could be trying to overlay an element in a different stacking context.
Groups of elements with a common parent that move forward or backward
together in the stacking order make up what is known as a stacking
context. A full understanding of stacking contexts is key to really
grasping how z-index and the stacking order work.
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!
~ What No One Told You About Z-Index
Stacking Order
CSS adheres to a stacking order when laying out elements on a page. These are the stacking rules when there is no z-index specified, from farthest to closest:
Backgrounds and borders of the root element
Non-positioned, non-floating block elements, in the order they appear in the source code
Non-positioned floating elements, in the order they appear in the source code
Inline elements
Positioned elements, in the order they appear in the source code
If a z-index property is applied, the stacking order is modified:
Backgrounds and borders of the root element
Positioned elements with a z-index of less than 0
Non-positioned, non-floating block elements, in the order they appear in the source code
Non-positioned floating elements, in the order they appear in the source code
Inline elements
Positioned elements, in the order they appear in the source code
Positioned elements with z-index of greater than 0
Source: W3C
Bottom line: Once you understand stacking contexts, z-index is easy.
For examples of z-index in action see: How z-index works!
For a brief but highly informative article explaining z-index (including how opacity affects the stacking order) see: What No One Told You About Z-Index
For a complete rundown on z-index, with many examples and illustrations, see: MDN Understanding CSS z-index
And for a deep dive into stacking contexts read: W3C Elaborate description of Stacking Contexts
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
How does z-index actually work?
Does it function on elements with no specified position?
Does it favor elements (i.e. make them on top) that have a specified position?
Do the numbers have to be negative like this?
<div style='z-index:-2;'>below</div>
<div style='z-index:-1;'>less below</div>
<div style='z-index:0;'>on top</div>
Or not? Would all positive numbers (in increasing value) end up with the last being on the top, the middle in the middle, and the first on the bottom?
Both negative and positive integers are allowed.
The position must be set on the element.
Before I get into those details, though, let me explain z-index from the ground up.
Every webpage is made up of what are called stacking contexts. You can think of these as, quite literally, a stack of elements. The z-index property determines the order of items in each stack, with higher z-index being placed further up.
All pages begin with a root stacking context, which builds from the root element (as you'd expect). But more stacking contexts can be created in a number of ways. One way is an absolutely positioned div; its children will be in a new stacking context.
The specs lists all of the instances that create a new stacking context. As others have stated, this includes explicitly positioned elements and will soon include elements that aren't completely opaque.
As I said before, z-index only takes effect if you explicitly set the position of the element. This means setting it to be fixed, absolute, or relative. This is best shown through example, I think.
In this example, we'd expect the blue div to be on top of the grey one given its z-index, right? But, as you can see, it's on the bottom. This is, of course, because we haven't set its position. Once we do that it displays as we'd expect. Again, you must set the position.
The specs also tell us that negative values are fine. With that said, you don't need to use negative values. It's perfectly fine to use positive integers, too. The default z-index value for an element is 0.
For the record, w3schools is a notoriously unreliable source for learning. While it can be a quick and convenient resource, there are lots of gaps in their information, and at times even wrong information. I recommend you to use more reliable sources like the Mozilla Developer Network, and also the specs themselves.
Before I start explaining, let me note that z-index only has an affect if the element has rendered value of position:relative, position:absolute, or position:fixed (NOT static) because each of these make it have its own stacking context. That means that values like initial or inherit may or may not work either depending on the situation.
Also note that in this post I'll be using the format 1.1.1 to signify that I am selecting the first element's first child's first child. 2.1.1 would be the second element's first child's first child and so on.
I think z-index is best explained with an analogy using sub lists. Let's start with the simplest example:
<div class="top-level"></div>
<div class="top-level sibling"></div>
We can represent this in terms of a list like so:
Top level
Top level sibling
Now by default the ones further down the list will render on top of the ones before it. So in this case 2 will be positioned on top of 1.
What z-index allows us to do is essentially reorder this list (within some bounds). The higher the z-index, the further down the list our element is.
I'll use inline CSS here to make showing it easy but you should definitely avoid inline CSS in production code.
<div class="top-level" style="z-index: 1;"></div>
<div class="top-level sibling"></div>
This now changes our sub listing to look like this:
Top level sibling
Top level - z-index:1
Great! Now the first element in our HTML will render on top of our second.
Where this gets more tricky is when we're dealing with children (nested) elements.
An easier way to think about this situation is to think that when an element starts being rendered it will render all children of the element before moving onto any siblings.
Also keep in mind that sub-lists cannot change levels, meaning they cannot be on the same level of their parent or their children elements.
That means that if we have the following:
<div class="top-level">
<div class="sub-level" style="z-index: 1;"></div>
</div>
<div class="top-level sibling"></div>
Our rendering sub lists will look like the following:
Top level
Sub level - z-index1
Top level sibling
Thus, we look our top level and see which one is at the bottom of the list. In this case, 2.0 is, so it will be on top of 1.0. Then we look and see if it has any sub lists (children). It doesn't, so we go to 1.0.
1.0 has a child, 1.1, which will be visually above 1.0 (just like it would be if we didn't give it a z-index), but it will still be below 2.0 because 1.0 is below 2.0.
Thus the z-index here doesn't help us out because 1.1 doesn't have any siblings.
Let's take a slightly more complex example:
<div class="top-level">
<div class="sub-level" style="z-index: 2;"></div>
<div class="sub-level sibling"></div>
<div class="sub-level sibling" style="z-index: 1;"></div>
</div>
<div class="top-level sibling">
<div class="sub-level"></div>
</div>
What's the sub listing for this example?
I'll give it to you, but it's good to try and do by yourself.
Top level
Sub level sibling
Sub level sibling - z-index1
Sub level - z-index2
Top level sibling
Sub level
Thus, in terms of what the order is visually from top to bottom, the order goes 2.1, 2.0, 1.3, 1.2. 1.1, 1.0.
That's not so bad, is it?
This behavior is true no matter how far deep or how many siblings are there.
The only exception to the rule that children are rendered above parents is when the children have a negative z-index. When a negative z-index is given, it places itself below a parent element.
Thus if we have the following:
<div class="top-level">
<div class="sub-level" style="z-index: -1;"></div>
</div>
<div class="top-level sibling"></div>
The sub list tree would look like this:
Sub level - z-index-1
Top level
Top level sibling
And the top to bottom layering would be 2.0, 1.0, 1.1.
A slightly more complex example:
<div class="top-level">
<div class="sub-level" style="z-index: -1;"></div>
<div class="sub-level sibling"></div>
</div>
<div class="top-level sibling"></div>
List representation:
Sub level - z-index-1
Top level
Sub level
Top level sibling
But you should avoid negative z-indexes. If you think you need them it is likely that your HTML is structured improperly.
That's about it! If you're still interested in learning more, reading the specs is always good.
Keep in mind that other properties, including but not limited to opacity, transform, and will-change, create their own stacking context and may have an affect on the rendering order of elements.
opacity works similarly to z-index - a child can only be as opaque as its parent - but it can't have negative values.
The only exception to the rule that children are rendered above parents is when the children have a negative z-index. When a negative z-index is given, it places itself below a parent element.
The css property z-index only works on positioned elements, meaning elements must be position absolute, fixed or relative in order for the z-index property to take effect.
The higher the z-index the closer to the front it will appear. The values specified for the z-index property can be positive or negative. A positioned element with a z-index value of 4 will appear above a positioned element with a z-index value of 3.
In CSS 2.1, each box has a position in three dimensions. In addition
to their horizontal and vertical positions, boxes lie along a "z-axis"
and are formatted one on top of the other. Z-axis positions are
particularly relevant when boxes overlap visually.
This article on z-index is just the link you are looking for! He really explains it well.
Basically, the higher the number, the higher up on the stack the element will be. So 1 is on top of 0 and -1 is under the z-index of 0, however they should be kept positive, as there is no reason to use negatives; it's considered bad practice. The browser interprets it when it renders the page, like any other CSS or HTML code.
I was trying to put something in my html which is located in a different area but has a high z-index so it should be on top. How does that work?
My example is something like this:
<div>
<div style="z-index: 7000"></div>
</div>
<div style = "z-index: 7050"></div>
I was thinking that z-index was only relavent to siblings in your DOM tree.
What do you all think about this?
This image sums it up nicely.
You can find a good article on how z-index property works within the stacking context here
Yes/No it will only effect things within the same group if the parent element is set to a position of relative. Everything inside of it from that point will inheret based off of that.
From what I see based on your above html however. z-index holds no value per say as the elements are not detattched from the DOM flow in a matter of speaking. z-index is for elements that have position: fixed or absolute
example:
<div style="z-index:100;"></div>
does nothing
<div>
<div style="z-index:100;"></div>
</div>
does nothing
<div style="position:relative;width:100px;height:100px;">
<div style="z-index:100;position:absolute;top:0;left:0;background-color:#000;"></div>
<div style="z-index:200;position:absolute;top:25px;left:25px;background-color:#CCC;"></div>
</div>
does something and keeps the elements within the parent div.
<div style="width:100px;height:100px;">
<div style="z-index:100;position:absolute;top:0;left:0;background-color:#000;"></div>
<div style="z-index:200;position:absolute;top:25px;left:25px;background-color:#CCC;"></div>
</div>
does something but the divs with z-index will use the browser as there medium of determining where to place themselves, rather than the parent element.
As chris already pointed out, it is important that the z-index property only applies to positioned elements. The spec says that the z-index property defines the positioning of elements within the same stacking context. Not every element generates a new stacking context! Thus, the z-index is not only relevant to siblings in the DOM tree, but to every element in the same stacking context. The spec says that elements that have auto instead of a integer for the z-index property do not generate a new stacking context.
Fast question; if you have 2 divs, one absolutley positioned and one relative, it isnt doing the z-index, i have attached a jsfiddle.
If i make them both relative they go with the flow of the DOM and one goes above the other on the y axis rather than z, any ideas?
Example JSfiddle (thanks Onheiron for fixing the render in jsfiddle)
Screenshot of whats happening: http://i.imgur.com/Lo37y.png , the gray thing should be behind the image.
Thanks.
You can't make a child appear behind it's parent! You can only do that with siblings.
See your updated fiddle
To answer this question, I need to explain stacking context.
When you add a z-index to an element, it creates a stacking context. All child elements are then compared to this parent stacking context.
Your element "slideImg" has a z-index of 1000. Any child elements are then compared within the stacking context of this parent element. So the z-index of "shadow", which is 0, is actually "1000 + 0", because it is within the stacking context of "slideImg".
To put "shadow" behind "slideImg" you can reverse their nesting:
<div id="shadow">
<div id="slideImg"></div>
</div>
Or put them adjacent to each other, so they are each considered in the same stacking context.
<div id="shadow"></div>
<div id="slideImg"></div>
There is an explanation of z-index and Stacking Context here.