Stop (ab)using z-index
Tags: css
Published: 2020-06-25 09:00:28

---
title: Stop (ab)using z-index
published: true
date: 2020-06-25 09:00:00 UTC
tags: CSS
canonical_url: https://www.codegram.com/blog/stop-ab-using-z-index/
---

`z-index: 2147483647`

I once saw this in a codebase. The number seemed so random that I thought it couldn't be that random, so I googled it. Turns out it's the highest value that the `z-index` property supports!

That developer must have been really desperate, but it's very common to see things like `z-index: 9999`, and if that doesn't work, let's keep adding `9`s until it does. You can guess what happens when you try to position something above that.

There are good solutions like [creating a z-index scale](https://gist.github.com/toadkicker/fc290e84d7bd861e3e73), which puts a bit sanity into the z-index nonsense, and we use this solution here at Codegram. But most of the time we don't even use the property at all, and when we use it we only use a couple of values. If you find yourself using more, either you have an extremely complex design that is very different from most sites in the internet (not likely), or you are using it wrong.

![Did you know you can code overlapping elements without using z-index at all?](https://www.codegram.com/blog/stop-ab-using-z-index/design.png)

### How z-index works

When working with CSS, we usually deal with two dimensions. However, when elements overlap and we need to adjust their order, we have to deal with a third dimension, the Z axis that the property `z-index` controls.

#### Positioning and order

Let's go over the basics: the `z-index` is a property related to positioning. By default, all elements have a `static` position. In order for `z-index` to have any effect at all, it needs to be applied to a positioned element, that means, an element with position `relative`, `absolute`, `fixed`, or `sticky`.

If you don't apply a `z-index`, the elements will be stacked in the order they are written in the HTML. Check this example:

{% codepen https://codepen.io/nuria-fl/pen/NWxpEPV %}

The text is not positioned, so it's behind everything. The other elements stack above each other in the order they are written in the HTML.

If we want this to match the design, we could add a `z-index: 1` to the illustration, and `position: relative` and `z-index: 2` to the `.hero__title` element. It's a good idea to always start with the lowest `z-index` value you can, to keep things simple.

{% codepen https://codepen.io/nuria-fl/pen/pogeqVa %}

But when working with CSS, it's always best if we can rely on the natural order of the elements and avoid altering the flow ourselves, to keep our code simple and scalable. As long as it makes sense, we could adjust the order of the items in the HTML, placing the text as the last element, and by applying `position: relative` to it, it wouldn't be necessary to use `z-index` at all:

{% codepen https://codepen.io/nuria-fl/pen/ZEQemWW %}

Of course, this approach has certain limitations, sometimes it is not possible to change the HTML, and changing the order arbitrarily should only be done to elements that don't have meaning, so we don't alter the experience of users who use screen-readers.

You can read more about [stacking without the z-index property](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/Stacking_without_z-index) at the MDN web docs.

#### Stacking contexts

Following the previous example, let's imagine that it's part of an external library and we do not have control over the code, we cannot alter its HTML or CSS and, to make things worse, the `.hero__title` element has a `z-index: 9999`. Now, let's say we need to add a modal to the same page. Which `z-index` value do you think the modal should have?

Your first reaction might be: oh dear, I should increase that modal `z-index` to `99999`, otherwise it will fall below the title, and here they come, the bad practises we wanted to avoid in the first place. But we can avoid this: `z-index` only competes with sibling elements within the same [stacking context](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context).

Even if the `.hero__title` has a `z-index: 9999`, we can place it inside a container with `position: relative` and `z-index: 1`, creating a new stacking context. Each stacking context is completely independent of its siblings: the descendants from each context will not interfere with elements outside. This way, we can position the modal above the hero just by adding a `z-index: 1`.

{% codepen https://codepen.io/nuria-fl/pen/wvMJQPV %}

### Take-aways

To sum up, always keep in mind these tips when positioning elements:

- Understand how stacking works, and use the rules to your advantage to avoid using `z-index`, as long as it makes sense.
- Keep `z-index` values low: you'll rarely need more than `z-index: 1` (or less than `z-index: -1`)
- Create stacking contexts to keep things boxed and prevent them from interfering with each other.

### Further reading

- [Understanding CSS z-index](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index)
- [CSS position docs](https://developer.mozilla.org/en-US/docs/Web/CSS/position)
- [CSS z-index docs](https://developer.mozilla.org/en-US/docs/Web/CSS/z-index)