What z-index value should you use? (tricky question)
Usually, the z-index property doesn’t represent a complicated aspect of a front-end project. You use this property to place elements in front of, or behind other elements, and depending on what you are building. Sometimes you don’t even need to touch this property.
However, in this article we want to explore some nuances around this property. Especially when its thoughtless use causes hard-to-debug issues.
What is the problem?
The issue with this property is that it is very common to see people using arbitrary high — or low — values, without a clear strategy or understanding of how it affects the stacking context. This can lead to layers overlapping in unexpected ways, making the debugging process challenging and tedious.
On top of that, unless you have a specific setup in your environment, CSS won’t complain about the value itself, even if you add a repeated one, or even if you add a value that exceeds the limit of the browser, it will accept it.
Two key issues that arise from improper use of z-index
- Maintainability challenges in large projects with several and inconsistent z-index values.
- Unexpected element overlapping due to a lack of understanding of stacking contexts.
By addressing these aspects, we aim to help you develop a more structured and effective approach to using the z-index property.
Let’s take a look at the following example. Assume your page has a modal and a banner and identify what is the issue here.
HTML:
<div class="banner">Banner</div>
<div class="modal">
<div class="modal-overlay"></div>
<div class="modal-content">Modal Content</div>
</div>
CSS:
.banner {
z-index: 37;
// more styles here
}
.modal {
z-index: 20;
// more styles here
}
/* Modal styles */
.modal-overlay {
z-index: 50;
// more styles here
}
.modal-content {
z-index: 37;
// more styles here
}
In this case, the modal and its overlay will be placed on top of most elements on the page, but the banner would still be visible even when the modal is active. This is usually not the desired behavior for a modal with an overlay, which should typically appear above all other page elements to focus the user’s attention.
There are two main problems with this approach:
1. The z-index values were added without any kind of system in mind. The seemingly arbitrary numbers (37, 20, 50, 37) make it difficult to quickly understand the intended stacking order.
2. This example doesn’t properly consider the stacking context. Even though the modal-overlay has a higher z-index than the banner class, both elements are lower than the banner’s z-index, causing the unintended layering.
This scenario illustrates why it’s critical to approach z-index values systematically, considering the entire page layout and the desired interactions between elements.
Stacking contexts
Stacking context is a three-dimensional conceptualization of HTML elements along an imaginary z-axis relative to the user. (MDN Docs, Stacking Context).
In other words, you can think of the stacking context as a box, you can place anything you want there, but you can have multiple boxes, if you have a box A, and on top of it you have box B, it doesn’t matter the value of the z-index of the elements inside box A, anything on box B would still be on top of them, even if you have repeated or lower values.
When do you create new stacking contexts?
There are several situations that create a new stacking context. These are the most common ones:
- The root element of the document (HTML): The root element always creates a new stacking context.
- Positioned elements: Any element with a position value of absolute, relative, fixed, or sticky and a z-index value other than auto creates a new stacking context.
- Elements with opacity less than 1.
- Transform and filter properties: Any element with a transform value other than none or a filter value other than none.
- CSS properties like perspective, clip-path, and mask: These properties also create new stacking contexts when applied to elements.
- Flexbox and Grid elements: Any element that is a flex container (display: flex or display: inline-flex) or a grid container (display: grid or display: inline-grid) and has a z-index value other than auto creates a new stacking context.
- CSS properties like will-change and contain.
You can check the full list in the MDN Docs page about Stacking Context.
Best practices you can follow
Some of these recommendations may exclude each other; you don’t need to apply everything you see here. Instead, pick what works best for you and your use case.
- Use a Standard for the Numbers: Any standard is better than not having one at all. If you and your team decide to use only tens (10, 20, 30, 40, and so on), then stick to only tens. This approach helps avoid arbitrary values such as 35, 13, and 17.
- Avoid Magic Numbers: Avoid using unexplained magic numbers for z-index values. Each value should have a reason and be documented.
- Minimize the Number of Stacking Contexts: Only create new stacking contexts when necessary. This helps keep the stacking order simpler and easier to understand.
- Leverage CSS Variables: Use CSS custom properties (or Sass variables if you are using it) to manage z-index values. This makes it easier to update values globally and maintain consistency. Take a look at how Bootstrap addresses this.
- Document Your z-index Values: Keep a record of the z-index values used across your project. This avoids conflicts and ensures consistency.
- Add comments: If your project doesn’t use CSS custom properties or layers and you update some z-index values, at least you can add a comment explaining why you are doing that. The following (simplified) example demonstrates how helpful this can be:
.legal-modal {
z-index: 2000 // Updating z-index to put this on top of Bootstrap modal
// other styles
}
Final thoughts and recap
Using the z-index property might seem straightforward at first, but it can quickly lead to complex issues if not managed correctly. By understanding and leveraging stacking contexts, adopting a systematic approach to assigning z-index values, and following best practices, you can ensure a more maintainable and predictable layout for your web projects.
Keep in mind that this whole topic doesn’t require you to reinvent the wheel. If you use a framework such as Bootstrap, then use its components and predefined z-index values whenever possible. These frameworks are designed with best practices in mind, and by leveraging their established conventions, you can avoid many common pitfalls associated with z-index and stacking contexts.
Quick recap:
- You need to understand what the stacking context is.
- Follow conventions.
- Document aspects that may look odd to a third party.
- If you use a tool, for example a framework, try to leverage it as much as possible.