CSS z-order is odd

I’ve had some problems recently that I finally determined were just CSS acting the way it’s supposed to, which is not how my intuition told me it should. (Neither the first nor the last time for that, I’m sure.) They were all elements of the page failing to show despite being visible from the developer tools, taking up space, being in the appropriate location, etc. The first one I noticed was background color, which led me down twisty side streets of containers whose elements are all floated and hence have no height, but all of the issues had one source: stacking order is much more complicated than I thought.

In my flailing for anything that might do something, I tried setting position: relative; on one of the problematic divs. Setting position had fixed other problems, but I didn’t expect it to fix this one. It did, though. What on earth could position have to do with visibility? My assumption had been that “later in the code” = “further to the front” unless changed by setting a z-index, but that is false. Position affects all three axes.

The specs are at w3.org as always and a more explanatory version is at Vanseo Design. The source of my problem, briefly stated, is that positioned elements bubble to the front of unpositioned elements even if you haven’t set a z-index on them.

In both cases my layout was something like this:

<div class="fixed-background div-1"> </div>

<div class="wrapper div-2">
	<div class="interior-positioned div-3">
		Might be an image but we'll just use text
		and a background color.
	</div>
	<div class="interior-unpositioned div-4">
		Text and a background color, ooh.
	</div>
</div> <!-- .div-2 -->

…with (positional and size) styling as so (we don’t style color schemes like this, promise):

.fixed-background {
	height: 100%;
	width: 100%;
	position: fixed;
	background-color: thistle;
}

.interior-positioned {
	position: relative;
	background-color: lightcoral;
	color: indigo;
}

.interior-unpositioned {
	background-color: mediumslateblue;
	color: midnightblue;
}

Div-1 and div-3 show up fine, but div-4 is invisible! Since div-1 has position set, it sits in front of div-2 and all of div-2’s unpositioned content. Setting position: relative on either div-2 or div-4 fixes the problem.

Try it yourself: here’s the page; from within your developer tools set position: relative; on either .wrapper or .interior-unpositioned and watch a second line poof into existence.

Leave a Reply

Your email address will not be published. Required fields are marked *