How to Find the Highest z-index on a Page in JavaScript
When you are dynamically creating UI elements like modals, pop-ups, or toasts, you often need to ensure they appear on top of all other content. To do this reliably, you must find the current highest z-index value on the page and set your new element's z-index to a value greater than that.
This guide will teach you a robust, modern method for scanning the DOM to find the maximum z-index. You will learn why this task is more complex than it seems and the critical performance considerations to keep in mind.
The Core Challenges
Finding the highest z-index is not as simple as reading a single property. There are two main challenges:
- Styles Can Come from Anywhere: A
z-indexcan be set in an inlinestyleattribute, an internal<style>block, or an external CSS file. You cannot simply useelement.style.zIndex, as this only reads inline styles. You must usewindow.getComputedStyle()to get the final, rendered style. z-indexDefaults toauto: For most elements,getComputedStyle(element).zIndexwill return the string"auto", not a number. When you try to parse this (parseInt('auto')), you getNaN(Not-a-Number), which you must handle correctly.
The Modern Solution (Recommended)
The most reliable solution is to iterate through all elements on the page, get their computed z-index, and keep track of the highest numeric value you find. This function is a clear and readable implementation of that logic.
Example of reausable function:
/**
* Finds the highest z-index value currently on the page.
* @returns {number} The maximum z-index found.
*/
function findMaxZIndex() {
// 1. Get all elements on the page
const allElements = document.querySelectorAll('body *');
let maxZ = 0;
// 2. Loop through them
for (const element of allElements) {
// 3. Get the computed z-index
const zIndex = window.getComputedStyle(element).zIndex;
// 4. Parse it as a number, ignoring 'auto' (which becomes NaN)
const zIndexNum = parseInt(zIndex, 10);
// 5. Keep track of the highest valid number
if (!isNaN(zIndexNum) && zIndexNum > maxZ) {
maxZ = zIndexNum;
}
}
return maxZ;
}
Solution:
// Example Usage:
const highestZIndex = findMaxZIndex();
console.log(`The highest z-index on the page is: ${highestZIndex}`);
// To place a new element on top of everything:
const myModal = document.getElementById('my-modal');
myModal.style.zIndex = highestZIndex + 1;
How the Solution Works
document.querySelectorAll('body *'): This selects every single element that is a descendant of the<body>.for (const element of allElements): We loop through this collection of elements.window.getComputedStyle(element).zIndex: For each element, we get its final, renderedz-indexvalue as a string.parseInt(zIndex, 10): We attempt to convert this string to a base-10 integer. IfzIndexwas"auto", this results inNaN.!isNaN(zIndexNum) && zIndexNum > maxZ: This is the core logic. We first check if the result is a valid number (notNaN). If it is, we then check if it's greater than the highest value we've seen so far. If both are true, we update ourmaxZ.return maxZ: After checking all elements,maxZwill hold the highest numericz-indexfound. We initialize it to0to handle cases where no elements have az-index.
A Note on the "One-Liner" Approach
You may see this logic written as a dense, functional one-liner. While concise, it is often harder to read and debug.
function getMaxZIndexOneLiner() {
return Math.max(
...Array.from(document.querySelectorAll('body *'), el =>
parseInt(window.getComputedStyle(el).zIndex)
).filter(zIndex => !isNaN(zIndex)),
0
);
}
This code performs the exact same steps as our more readable function but uses Array.from with a mapping function, filter, and the spread (...) operator. For maintainability, the step-by-step for...of loop is often preferred.
Performance Considerations
The biggest drawback of this method is performance. The document.querySelectorAll('body *') command can be very slow on large, complex web pages with thousands of elements, as the script must iterate over every single one.
- For most websites and applications, this is perfectly fine. The operation is fast enough that it won't be noticeable.
- For complex Single-Page Applications (SPAs) or pages with infinite scrolling, running this function frequently could become a bottleneck.
In such high-performance scenarios, a more advanced strategy might be needed, such as only querying elements that are likely to have a z-index (e.g., those with position: absolute or fixed), or maintaining the max z-index in a global state manager.
Conclusion
Finding the highest z-index requires a full DOM scan that correctly handles computed styles and non-numeric values.
- The most reliable method is to iterate through all elements, use
window.getComputedStyle()to read thezIndex, and parse the value, ignoringNaNresults. - A
for...ofloop provides a clear and readable implementation of this logic. - Be mindful of the performance implications on very large and complex pages, although for most use cases, the approach is perfectly acceptable.
By using this technique, you can reliably ensure that your dynamically created elements always appear on top of existing content.