In this example we have:
position: absolute nav element, positioned relative to...position: relative header element which is its immediate parent.Despite the fact the nav has z-index: 1, it appears underneath the .main div element that appears later in the markup.
So, thanks to "What no one told you about z-index", we know the following:
html elementposition other than static and z-index other than autoopacity other than 1z-index values (ties broken by order of appearance in the DOM)z-index: auto (in the order they appear in the DOM)z-index values (ties broken by order of appearance in DOM)The fact that no value of z-index on the nav element is sufficient to make it appear in front of the .main element indicates that we must have two stacking contexts at play here.
If we remove the erroneous position: relative on the .main element, then our z-index takes effect.
What could be creating a stacking context other than the root html element, given that no elements in our example have opacity other than 1, and no elements have non-static position and non-auto z-index?
Here header and .main are peers, and both are positioned. Neither has a z-index. Clearly, however, header forms a stacking context, because the z-index of elements inside it are unable to ever appear in front of anything outside the header.
.main ends up trumping anything in header, because .main appears after it in the DOM.
So, the stacking context is formed inside header because it is positioned, and it contains a descendent with a z-index. "Creation rule #2" above, "[e]lements with position other than static and z-index other than auto", makes it sound like the position and z-index must be on the same element, but this example makes it clear that that is not the case. Perhaps it is true that the non-auto z-index on the descendant forces the parent to have an implicit z-index of 0 (although the DOM inspector seems to refute this, showing an inherited value of auto).
An alternative explanation is that the two peers that are positioned will always appear relative to one another in the DOM due to "ordering rule #4". This in turn makes z-index pretty useless inside positioned elements, at least with respect to other positioned elements. Note that even setting a smaller z-index on the trumping value is not enough to fix the problem.
I think to fully lay this to rest I'll need to get a university degree in the spec.