Stack elements with HTML and CSS

Learn how do browsers order elements on the z axis, and how to use CSS z-index.

Default order

No z-index applied and no positionning (elements are position:static by default). Elements are drawn by browsers in the order they appear in the HTML code: the last element declared is on top.

HTML
div
↳ div class="blue"
↳ div class="red"

Default order with positionning

No z-index applied, some elements are positioned. Browser first draw non positioned elements in the order they appear in the HTML code, then draw positioned elements in the order they appear in the HTML code.

HTML
div
↳ div class="blue"
↳ div class="yellow"
↳ div class="green"
↳ div class="red"
CSS
.blue, .yellow, .green {position:absolute }

Stack order with z-index

An element with a higher z-index will be displayed in front of an element with a lower z-index. Z-index only works with positioned elements.

That's why Webflow doesn't even allow you to add a z-index value to a non positioned element.

HTML
div
↳ div class="blue"
↳ div class="yellow"
↳ div class="green"
↳ div class="red"
CSS
.blue, .yellow, .green {position:absolute }
.green {z-index:2 }
.yellow {z-index:3 }

Stacking context

By adding a z-index to the blue div, we created a stacking context. The yellow div isn't on top of the green one even if it has a higher z-index value. What now counts is that the blue div and the green one are at the same level and both have z-index values.

From now on, the yellow div can't be placed above the green one anymore, because they're not in the same context. The z-index value of the yellow div now only has meaning inside of the context of the blue div.

HTML
div
↳ div class="blue"
↳ div class="yellow"
↳ div class="green"
↳ div class="red"
CSS
.blue, .yellow, .green {position:absolute }
.green {z-index:2 }
.yellow {z-index:3 }
.blue {z-index:1 }

Stacking context (2)

if we move the green div inside of the context of the blue one, the yellow div is now drawn back on top of it, as both share the same context and the yellow one has a higher z-index value.

From now on, the yellow div can't be placed above the blue one anymore, because they're not in the same context. The z-index value of the yellow div now only has meaning inside of the context of the blue div.

HTML
div
↳ div class="blue"
↳ div class="yellow"
↳ div class="green"
↳ div class="red"
CSS
.blue, .yellow, .green {position:absolute }
.green {z-index:2 }
.yellow {z-index:3 }
.blue {z-index:1 }

What properties form a stacking context?

Stacking contexts are not only formed when applying z-index to an element. There are several other properties that cause elements to form stacking contexts.

For example, it works with CSS filter. Here we applied a CSS filter to the blue div, which doens't have a z-index defined. Nevertheless, it forms a stacking context like in the previous examples.

Check what are all the properties that are creating a stacking context.

HTML
div
↳ div class="blue"
↳ div class="yellow"
↳ div class="green"
↳ div class="red"
CSS
.blue, .yellow, .green {position:absolute }
.green {z-index:2 }
.yellow {z-index:3 }
.blue {filter: hue-rotate(10deg) }

Final advices

In order to efficiently control the stack order of your elements, try to define z-index on elements that are at the same level. You'll avoid a lot of headaches around z-index. However defining z-index solely on elements that aren't at the same level in the DOM can be the solution to a challenging design layout.

Be aware that when you apply some CSS properties to an element, you're creating a stacking context.