z-index not working with fixed positioning
I have a div
with default positioning (i.e. position:static
) and a div
with a fixed
position.
If I set the z-indexes of the elements, it seems impossible to make the fixed element go behind the static element.
#over {
width: 600px;
z-index: 10;
}
#under {
position: fixed;
top: 5px;
width: 420px;
left: 20px;
border: 1px solid;
height: 10%;
background: #fff;
z-index: 1;
}
<!DOCTYPE html>
<html>
<body>
<div id="over">
Hello Hello HelloHelloHelloHelloHello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello
</div>
<div id="under">
</div>
</body>
</html>
Or on jsfiddle here: http://jsfiddle.net/mhFxf/
I can work around this by using
position:absolute
on the static element, but can anyone tell me why this is happening?
(There seems to be a similar question to this one, (Fixed Positioning breaking z-index) but it doesn't have a satisfactory answer, hence I am asking this here with my example code)
Add position: relative;
to #over
#over {
width: 600px;
z-index: 10;
position: relative;
}
#under {
position: fixed;
top: 5px;
width: 420px;
left: 20px;
border: 1px solid;
height: 10%;
background: #f0f;
z-index: 1;
}
<!DOCTYPE html>
<html>
<body>
<div id="over">
Hello Hello HelloHelloHelloHelloHello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello
</div>
<div id="under"></div>
</body>
</html>
Fiddle
This question can be solved in a number of ways, but really, knowing the stacking rules allows you to find the best answer that works for you.
Solutions
The <html>
element is your only stacking context, so just follow the stacking rules inside a stacking context and you will see that elements are stacked in this order
- The stacking context’s root element (the
<html>
element in this case)- 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)
So you can
- set a z-index of -1, for
#under
positioned -ve z-index appear behind non-positioned#over
element - set the position of
#over
torelative
so that rule 5 applies to it
The Real Problem
Developers should know the following before trying to change the stacking order of elements.
- When a stacking context is formed
- By default, the
<html>
element is the root element and is the first stacking context
- By default, the
- Stacking order within a stacking context
The Stacking order and stacking context rules below are from this link
When a stacking context is formed
- 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
- Several newer CSS properties also create stacking contexts. These include: transforms, filters, css-regions, paged media, and possibly others. https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context
- As a general rule, it seems that if a CSS property requires rendering in an offscreen context, it must create a new stacking context.
Stacking Order within a Stacking Context
The order of elements:
- The stacking context’s root element (the
<html>
element is the only stacking context by default, but any element can be a root element for a stacking context, see rules above)- You cannot put a child element behind a root stacking context 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)
since your over
div doesn't have a positioning, the z-index doesn't know where and how to position it (and with respect to what?). Just change your over div's position to relative, so there is no side effects on that div and then the under div will obey to your will.
here is your example on jsfiddle: Fiddle
edit: I see someone already mentioned this answer!
z-index only works within a particular context i.e. relative
, fixed
or absolute
position.
z-index for a relative div has nothing to do with the z-index
of an absolutely or fixed div.
EDIT This is an incomplete answer. This answer provides false information. Please review @Dansingerman's comment and example below.