Never Get Bit by z-index Again

Written by Ted Krueger

Sometimes I do things that make me very pleased with myself. I try to remain humble, but this is something that I thought fell into the too-good-not-to-share category. It has to do with z-index. Something that can be a developers worst enemy when writing css. What I’m about to share with you will hopefully ensure you never lose your z-index order again.

I’ve been trying to use a lot more custom properties when writing css. So far, it has allowed us to write cleaner and more customizable css. Typically I think of values like color, font-size, and size (height, width) as values where you might set a custom property. I never thought to use one for setting z-index on a component. Until today.

In case you’re not that familiar with how z-index really works, which is totally fine and understandable, let me give you a quick and dirty summary.

  • z-index will only work on those elements that are assigned a position other than static
  • elements are essentially assigned a natural z-index based on their order in the stack
    • I like to think of elements like a deck of cards. Each sibling is stacked on top of the previous element
  • nested elements with z-index won’t really do anything unless their parent element has a specific z-index
  • For a more indepth read on z-index I encourage you to read this post

We’re currently redesigning one of our websites, which will remain nameless, and we have some fixed elements at the top of the page. These elements require some z-index. We have a drawer that sits just below the header which contains some filters for a specific page. On this same page we want to show a table comparing selections, but we still want the filters to show. Not a problem, we just need to make sure one z-index is higher than the other.

Here’s what I did:

.filters {
  position: fixed;
  z-index: 10;
}

.comparison {
  position: absolute;
  /* make sure the z-index is always lower than the filters */
  z-index: 9;
}

I added that comment so that when we look at our code we know the value is important. Also, the comparison css is in a separate file and not actually directly underneath the filters css. So the comment makes a little more sense in that case.

As I was reading my own comment I realized there is a pretty solid way we could make sure the filters’ z-index potentially changing never affects the z-index of the comparison. Custom Properties and the CSS calc function to the rescue! Here’s what I came up with:

:root {
  --filters-zindex: 10;
}

.filters {
  position: fixed;
  z-index: var(--filters-zindex);
}

.comparison {
  position: absolute;
  /* make sure the z-index is always lower than the filters */
  z-index: calc(var(--filters-zindex) - 1);
}

Voilá! We shouldn’t need the comment anymore, but it doesn’t hurt to have it. With this method, any change to the filters z-index will not affect how the 2 elements stack.

Published April 11, 2023 by

undefined avatar
Ted Krueger UI/UX Developer

Suggested Reading