How to avoid Z-INDEX war

A summary of tricks learnt from Josh Comeau

In our applications, we can sometimes notice z-index of elements increase overtime as new requirements and components get added. There are times when the dropdown menus get hidden behind text input boxes or floating components bleed through modals after UI component upgrade.

There are 3 tricks that can help minimise the risk and avoid ever increasing z-index value.

1. Sensible DOM order with occasional z-index

By the natural flow of DOM order, the elements created later with non-static positions like position: absolute or position: relative can cover the elements created earlier.

It is important to have a sensible DOM order in which the tab navigation makes sense. In our diagram, we want the <Heading/> to always stick to the top, but it is likely to be overwritten by elements defined later such as <Main/>. In the case where we want earlier elements to appear on top of later elements, it is ok to use z-index on the <Heading/> in order to preserve the sensible DOM order.

2. Isolation: isolate

After z-index is defined, it may cause unexpected behaviour where the earlier element, <Heading/> covers up later element, <Help/>. This is because both <Heading/> and <Help/> share the same global stack context and <Heading/> has got higher z-index .

To get <Help/> above <Heading/> without adding higher z-index , we can get <Heading/> into a separate stacking context. That way, since <Heading/> and <Help/> are in different stacking context, the <Heading/> z-index will not affect <Help/>. <Help/> would appear to on top of <Heading/> due to the order of DOM elements.

// css, to put the heading into a separate stacking context
.heading-wrapper {
isolation: isolate;
}

3. Isolate <div id=”root” /> for Modal

If we use UI component libraries like Reach-UI, the DOM of the modal usually gets inserted below the root element, <id id="root" /> if using React. While all of the other elements in the app are most likely rendered inside the root element, the Modal, that gets rendered below would usually appear on the very top of the page when called open — if there is no other higher z-index in the stacking context.

To avoid potential bugs in future, it is best to put the whole root element into a separate stacking context by giving it isolation . That way, the z-index inside the elements in the root element will not interfere with the Modal. The Modal would always appear on top without any elements bleeding through accidentally.

#root{
isolation:isolate;
}

A software engineer passionate about learning and growth