DevPath · Learn to code ESPTEN

CSS: display, flow and positioning

z-index and stacking contexts

The axis you cannot see

Besides width and height, boxes live on a third axis: the Z axis, running from the screen toward you. It is depth. When two elements overlap, z-index decides which one stays in front: the higher the number, the closer to you. Think of a deck of cards on a table: the top card covers the ones below it.

.behind { position: absolute; z-index: 1; }
.front  { position: absolute; z-index: 2; }  /* covers .behind */

z-index only works with position

z-index only takes effect on positioned elements (that is, with a position other than static: relative, absolute, fixed or sticky). On a static element it is completely ignored.

⚠️ CLASSIC TRAP: setting z-index and forgetting the position. You crank the number up to 9999, nothing happens, and you start questioning your sanity. Before touching z-index, make sure the element is positioned.

.modal {
  position: fixed;   /* without this, the z-index would do nothing */
  z-index: 100;
}

Stacking contexts (intro)

A stacking context is an independent Z "bubble". Inside it, the children's z-index values only compete with each other, not with elements outside. An element creates a new context when, for example:

The practical consequence: a child with z-index: 9999 will never beat an element from another bubble whose parent has a higher z-index. If a modal "hides" behind something despite its huge z-index, the cause is almost always a stacking context created by an ancestor.

Key idea: Z order is resolved by levels, first between bubbles and then within each one. Keep few contexts and low, orderly numbers; your future self will thank you.

That wraps up classic placement. The next step is flexbox, where you stop pushing boxes around one by one and tell the container to lay them out for you.

Examples

The red circle stays in front because of its higher z-index

<style>
.zone { position: relative; height: 80px; }
.circle {
  position: absolute;
  top: 10px;
  width: 50px;
  height: 50px;
  border-radius: 50%;
}
.blue { left: 10px; background: #3b82f6; z-index: 1; }
.red  { left: 35px; background: #ef4444; z-index: 2; }
</style>
<div class="zone">
  <div class="circle blue"></div>
  <div class="circle red"></div>
</div>
Put this into practice

DevPath is a hands-on course: you read the theory here; in the app you put it into practice with exercises that really run, offline.

Start free in the app →
← The position propertyView the module →