How can you figure out the highest z-index in your document?

JavascriptHtmlCssZ Index

Javascript Problem Overview


In order to set a div containing a transparent text image as the highest z-index in my document, I picked the number 10,000 and it solved my problem.

Previously I had guessed with the number 3 but it had no effect.

So, is there a more scientific way of figuring out what z-index is higher than that of all of your other elements?

I tried looking for this metric in Firebug but couldn't find it.

Javascript Solutions


Solution 1 - Javascript

Stealing some code from abcoder site for the sake of clarity:

  var maxZ = Math.max.apply(null, 
    $.map($('body *'), function(e,n) {
      if ($(e).css('position') != 'static')
        return parseInt($(e).css('z-index')) || 1;
  }));

Solution 2 - Javascript

You could call findHighestZIndex for a particular element type such as <div> like this:

findHighestZIndex('div');

assuming a findHighestZindex function that is defined like this:

function findHighestZIndex(elem)
{
  var elems = document.getElementsByTagName(elem);
  var highest = Number.MIN_SAFE_INTEGER || -(Math.pow(2, 53) - 1);
  for (var i = 0; i < elems.length; i++)
  {
    var zindex = Number.parseInt(
      document.defaultView.getComputedStyle(elems[i], null).getPropertyValue("z-index"),
      10
    );
    if (zindex > highest)
    {
      highest = zindex;
    }
  }
  return highest;
}

Solution 3 - Javascript

Using ES6 a cleaner approach

function maxZIndex() {
    
     return Array.from(document.querySelectorAll('body *'))
           .map(a => parseFloat(window.getComputedStyle(a).zIndex))
           .filter(a => !isNaN(a))
           .sort()
           .pop();
}

Solution 4 - Javascript

I’d like to add my ECMAScript 6 implementation that I use in one of my UserScripts. I’m using this one to define the z-index of specific elements so that they always appear the highest.

In JS, you can additionally set certain attributes or class names to elements that you may want to exclude. For instance, consider your script setting a data-highest attribute on an element that you want to appear as the highest element (e.g. a popup); and consider an element with class name yetHigher that you don’t control, which should be even higher (e.g. a custom context menu). I can exclude these elements with a chained :not selector. Note that :not([data-highest], .yetHigher) is possible, but experimental, and only has limited browser support as of January 2021.

let highestZIndex = 0;

// Then later, potentially repeatedly
highestZIndex = Math.max(
  highestZIndex,
  ...Array.from(document.querySelectorAll("body *:not([data-highest]):not(.yetHigher)"), (elem) => parseFloat(getComputedStyle(elem).zIndex))
    .filter((zIndex) => !isNaN(zIndex))
);

The lower five lines can run multiple times and update the variable highestZIndex repeatedly by finding out the maximum between the current highestZIndex value and all the other computed z-indexes of all elements. The filter excludes all the "auto" values.

Solution 5 - Javascript

There isn't a default property or anything, but you could write some javascript to loop through all elements and figure it out. Or if you use a DOM management library like jQuery, you could extend its methods (or find out if it supports it already) so that it starts tracking element z-indices from page load, and then it becomes trivial to retrieve the highest z-index.

Solution 6 - Javascript

I believe what you are observing is Voodoo. Without access to your complete style sheet I can of course not tell reliably; but it strikes me as likely that what really has happened here is that you have forgotten that only positioned elements are affected by z-index.

Additionally, z-indexes aren't assigned automatically, only in style sheets, which means that with no other z-indexed elements, z-index:1; will be on top of everything else.

Solution 7 - Javascript

I guess you have to do this yourself ...

function findHighestZIndex()
{
    var divs = document.getElementsByTagName('div');
    var highest = 0;
    for (var i = 0; i < divs .length; i++)
    {
        var zindex = divs[i].style.zIndex;
        if (zindex > highest) {
            highest = zindex;
        }
    }
    return highest;
}

Solution 8 - Javascript

The best way to solve this problem is, in my opinion, just to set yourself conventions for what kinds of z-indexes are used for different kinds of elements. Then, you'll find the correct z-index to use by looking back at your documentation.

Solution 9 - Javascript

The "ES6" version above is less efficient than the first solution because it does multiple redundant passes across the full array. Instead try:

findHighestZ = () =>
  [...document.querySelectorAll('body *')]
    .map(elt => parseFloat(getComputedStyle(elt).zIndex))
    .reduce((highest, z) => z > highest ? z : highest, 1)

In theory it would be even quicker to do it in one reduce step, but some quick benchmarking showed no significant difference, and the code is gnarlier

Solution 10 - Javascript

Using jQuery:

if no elements supplied, it checks all elements.

function maxZIndex(elems)
{
	var maxIndex = 0;
	elems = typeof elems !== 'undefined' ? elems : $("*");

	$(elems).each(function(){
					  maxIndex = (parseInt(maxIndex) < parseInt($(this).css('z-index'))) ? parseInt($(this).css('z-index')) : maxIndex;
					  });

return maxIndex;
}

Solution 11 - Javascript

I had to do this for a project recently, and I found that I benefitted a lot from @Philippe Gerber's great answer here, and @flo's great answer (the accepted answer).

The key differences to the answers referenced above are:

  • Both the CSS z-index, and any inline z-index style are calculated, and use the larger of the two for comparison and calculation.
  • Values are coerced into integers, and any string values (auto, static, etc) are ignored.

Here is a CodePen for the code example, but it's included here as well.

(() => {
  /**
   * Determines is the value is numeric or not.
   * See: https://stackoverflow.com/a/9716488/1058612.
   * @param {*} val The value to test for numeric type.
   * @return {boolean} Whether the value is numeric or not.
   */
  function isNumeric(val) {
    return !isNaN(parseFloat(val)) && isFinite(val);
  }

  
  /**
   * Finds the highest index in the current document.
   * Derived from the following great examples:
   *  [1] https://stackoverflow.com/a/1118216/1058612
   *  [2] https://stackoverflow.com/a/1118217/1058612
   * @return {number} An integer representing the value of the highest z-index.
   */
  function findHighestZIndex() {
    let queryObject = document.querySelectorAll('*');
    let childNodes = Object.keys(queryObject).map(key => queryObject[key]);
    let highest = 0;
    
    childNodes.forEach((node) => {
      // Get the calculated CSS z-index value.
      let cssStyles = document.defaultView.getComputedStyle(node);
      let cssZIndex = cssStyles.getPropertyValue('z-index');
      
      // Get any inline z-index value.
      let inlineZIndex = node.style.zIndex;

      // Coerce the values as integers for comparison.
      cssZIndex = isNumeric(cssZIndex) ? parseInt(cssZIndex, 10) : 0;
      inlineZIndex = isNumeric(inlineZIndex) ? parseInt(inlineZIndex, 10) : 0;
      
      // Take the highest z-index for this element, whether inline or from CSS.
      let currentZIndex = cssZIndex > inlineZIndex ? cssZIndex : inlineZIndex;
      
      if ((currentZIndex > highest)) {
        highest = currentZIndex;
      }
    });

    return highest;
  }

  console.log('Highest Z', findHighestZIndex());
})();

#root {
  background-color: #333;
}

.first-child {
  background-color: #fff;
  display: inline-block;
  height: 100px;
  width: 100px;
}

.second-child {
  background-color: #00ff00;
  display: block;
  height: 90%;
  width: 90%;
  padding: 0;
  margin: 5%;
}

.third-child {
  background-color: #0000ff;
  display: block;
  height: 90%;
  width: 90%;
  padding: 0;
  margin: 5%;
}

.nested-high-z-index {
  position: absolute;
  z-index: 9999;
}

<div id="root" style="z-index: 10">
  <div class="first-child" style="z-index: 11">
    <div class="second-child" style="z-index: 12"></div>
  </div>
  <div class="first-child" style="z-index: 13">
    <div class="second-child" style="z-index: 14"></div>
  </div>
  <div class="first-child" style="z-index: 15">
    <div class="second-child" style="z-index: 16"></div>
  </div>
  <div class="first-child" style="z-index: 17">
    <div class="second-child" style="z-index: 18">
      <div class="third-child" style="z-index: 19">
        <div class="nested-high-z-index">Hello!!! </div>
      </div>
    </div>
  </div>
  <div class="first-child">
    <div class="second-child"></div>
  </div>
  <div class="first-child">
    <div class="second-child"></div>
  </div>
  <div class="first-child">
    <div class="second-child"></div>
  </div>
</div>

Solution 12 - Javascript

Array.reduce()

Here's another solution to determine the topmost z-index that uses Array.reduce():

const max_zindex = [...document.querySelectorAll('body *')].reduce((accumulator, current_value) => {
  current_value = +getComputedStyle(current_value).zIndex;
  
  if (current_value === current_value) { // Not NaN
    return Math.max(accumulator, current_value)
  }
  
  return accumulator;
}, 0); // Default Z-Index Rendering Layer 0 (Zero)

Solution 13 - Javascript

ShadowRoot solutions

We must not forget about custom-elements and shadow-root content.

function computeMaxZIndex() {
    function getMaxZIndex(parent, current_z = 0) {
        const z = parent.style.zIndex != "" ? parseInt(parent.style.zIndex, 10) : 0;
        if (z > current_z)
            current_z = z;
        const children = parent.shadowRoot ? parent.shadowRoot.children : parent.children;
        for (let i = 0; i < children.length; i++) {
            const child = children[i];
            current_z = getMaxZIndex(child, current_z);
        }
        return current_z;
    }
    return getMaxZIndex(document.body) + 1;
}

Solution 14 - Javascript

A solution highly inspired from the excellent idea of @Rajkeshwar Prasad .

	/**
	returns highest z-index
	@param {HTMLElement} [target] highest z-index applyed to target if it is an HTMLElement.
	@return {number} the highest z-index.
	*/
	var maxZIndex=function(target) {
	    if(target instanceof HTMLElement){
	        return (target.style.zIndex=maxZIndex()+1);
	    }else{
	        var zi,tmp=Array.from(document.querySelectorAll('body *'))
	            .map(a => parseFloat(window.getComputedStyle(a).zIndex));
	        zi=tmp.length;
	        tmp=tmp.filter(a => !isNaN(a));
	        return tmp.length?Math.max(tmp.sort((a,b) => a-b).pop(),zi):zi;
	    }
	};

#layer_1,#layer_2,#layer_3{
  position:absolute;
  border:solid 1px #000;
  width:100px;
  height:100px;
}
#layer_1{
  left:10px;
  top:10px;
  background-color:#f00;
}
#layer_2{
  left:60px;
  top:20px;
  background-color:#0f0;
  z-index:150;
}
#layer_3{
  left:20px;
  top:60px;
  background-color:#00f;
}

<div id="layer_1" onclick="maxZIndex(this)">layer_1</div>
<div id="layer_2" onclick="maxZIndex(this)">layer_2</div>
<div id="layer_3" onclick="maxZIndex(this)">layer_3</div>

Solution 15 - Javascript

If you're looking to show the IDs of all elements with the highest z indices:

function show_highest_z() {
    z_inds = []
    ids = []
    res = []
    $.map($('body *'), function(e, n) {
        if ($(e).css('position') != 'static') {
            z_inds.push(parseFloat($(e).css('z-index')) || 1)
            ids.push($(e).attr('id'))
        }
    })
    max_z = Math.max.apply(null, z_inds)
    for (i = 0; i < z_inds.length; i++) {
        if (z_inds[i] == max_z) {
            inner = {}
            inner.id = ids[i]
            inner.z_index = z_inds[i]
            res.push(inner)
        }
    }
    return (res)
}

Usage:

show_highest_z()

Result:

[{	"id": "overlay_LlI4wrVtcuBcSof",	"z_index": 999999}, {	"id": "overlay_IZ2l6piwCNpKxAH",	"z_index": 999999}]

Solution 16 - Javascript

Robust solution to find maximum zIndex in NodeList

  1. You should check both getComputedStyle and style object provided by node itself
  2. Use Number.isNaN instead of isNaN because of isNaN("") === false
function convertToNumber(value) {
  const asNumber = parseFloat(value);
  return Number.isNaN(asNumber) ? 0 : asNumber;
}

function getNodeZIndex(node) {
  const computedIndex = convertToNumber(window.getComputedStyle(node).zIndex);
  const styleIndex = convertToNumber(node.style.zIndex);

  if (computedIndex > styleIndex) {
    return computedIndex;
  }

  return styleIndex;
}

function getMaxZIndex(nodeList) {
  const zIndexes = Array.from(nodeList).map(getNodeZIndex);
  return Math.max(...zIndexes);
}

const maxZIndex = getMaxZIndex(document.querySelectorAll("body *"));

Solution 17 - Javascript

Very simple code using map and filter

function calMaxZIndex() {
  return Array.from(document.querySelectorAll('body *'))
    .map(a => parseFloat(window.getComputedStyle(a).zIndex || a.style.zIndex))
    .filter(a => !isNaN(a))
    .sort()
    .pop()
}

function getMax() {
  const max = calMaxZIndex() ?? 0
  console.log({
    max
  })
}

getMax()

#ticket-box {
  text-align: center;
  position: fixed;
  top: 0;
  right: 0;
  width: 100%;
  background-color: #e9d295;
  padding: 5px;
  z-index: 6;
}

<div id="menu">
  <a href="javascript:void(0);" onclick="closeMenu();" style="color: #ffffff; position: absolute; top: 15px; right: 15px;text-decoration: none;">CLOSE</a>

  <ul style="text-align:center;list-style-type:none;">
    <li><a href="#">FILM</a></li>
    <li><a href="#">MUSIC</a></li>
    <li><a href="#">SPORTS</a></li>
    <li><a href="#">FINANCE</a></li>
  </ul>
</div>

<div id="ticket-box">Have you bought your tickets for friday's event? No?! <a href="#">Grab yours now!</a></div>

<center><a href="javascript:void(0);" onclick="revealMenu();" style="display: inline-block; color: #333333; margin-top: 90px;">MENU</a></center>

Solution 18 - Javascript

Based on previous answers:

function with some modifications
let zIndexMax = () =>
    [...document.querySelectorAll('body > *')]
        .map(elem => parseInt(getComputedStyle(elem).zIndex, 10) || 0)
        .reduce((prev, curr) => curr > prev ? curr : prev, 1);
Prototype
HTMLElement.prototype.zIndexMax = function () {
    return [...this.children]
        .map(elem => parseInt(getComputedStyle(elem).zIndex, 10) || 0)
        .reduce((prev, curr) => curr > prev ? curr : prev, 1);
}

usage

document.querySelector('body').zIndexMax();

Solution 19 - Javascript

After looking through a lot of solutions here on StackOverflow - I've seen that none of them actually works correctly and considers how is zIndex actually working. I have written a solution that also takes into consideration the stacking context. You can refer to this article to understand how stacking context works in CSS.

const getZIndex = el => {
  const computedStyle = getComputedStyle(el, null)
  const zIndex = computedStyle.getPropertyValue('z-index')
  return zIndex !== 'auto' ? parseInt(zIndex) : null
}

const getZIndexWithinStackingContext = (el, context) => {
  let zIndex = getZIndex(el)
  if (!zIndex) return null

  let result = zIndex

  while (el.parentElement !== context) {
    el = el.parentElement
    zIndex = getZIndex(el)
    if (zIndex) {
      result = zIndex
    }
  }

  return result
}

const createZIndex = (overVisibleOnly = false, context = document.body) => {
  const elements = [...document.querySelectorAll('body *')]
  let highestZIndex = 0

  elements.forEach(el => {
    if (overVisibleOnly) {
      const isVisible = !!el.offsetParent
      if (!isVisible) return
    }

    const zIndex = getZIndexWithinStackingContext(el, context)

    if (zIndex && zIndex > highestZIndex) {
      highestZIndex = zIndex
    }
  })

  return highestZIndex + 1
}

Note that this solution considers all elements, and not only positioned ones because they can become positioned after some class is added. But you can fix this easily by just adding a check for the position computed style property.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCharlie KotterView Question on Stackoverflow
Solution 1 - JavascriptJimmy ChandraView Answer on Stackoverflow
Solution 2 - JavascriptfloView Answer on Stackoverflow
Solution 3 - JavascriptRajkeshwar PrasadView Answer on Stackoverflow
Solution 4 - JavascriptSebastian SimonView Answer on Stackoverflow
Solution 5 - JavascriptRahulView Answer on Stackoverflow
Solution 6 - JavascriptWilliham TotlandView Answer on Stackoverflow
Solution 7 - JavascriptPhilippe GerberView Answer on Stackoverflow
Solution 8 - JavascriptGarethView Answer on Stackoverflow
Solution 9 - JavascriptpodpersonView Answer on Stackoverflow
Solution 10 - JavascriptMisfer AliView Answer on Stackoverflow
Solution 11 - JavascriptUser 1058612View Answer on Stackoverflow
Solution 12 - JavascriptGrant MillerView Answer on Stackoverflow
Solution 13 - JavascriptAdam JosefusView Answer on Stackoverflow
Solution 14 - JavascriptyorgView Answer on Stackoverflow
Solution 15 - JavascriptCyberneticView Answer on Stackoverflow
Solution 16 - JavascriptDaniel BultasView Answer on Stackoverflow
Solution 17 - JavascriptTeocciView Answer on Stackoverflow
Solution 18 - JavascriptMarek LisieckiView Answer on Stackoverflow
Solution 19 - JavascriptKiloByteView Answer on Stackoverflow