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

43,954

Solution 1

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 2

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 3

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

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

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.

Share:
43,954
Charlie Kotter
Author by

Charlie Kotter

Updated on February 20, 2022

Comments

  • Charlie Kotter
    Charlie Kotter about 2 years

    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.

  • Williham Totland
    Williham Totland almost 15 years
    Except, of course, that any element can be positioned and z-indexed, not just divs.
  • Boldewyn
    Boldewyn almost 15 years
    Problem is, that element.style.zIndex doesn't find z-indices set in external stylesheets. Google for getComputedStyle to find that ones.
  • Matthew Lock
    Matthew Lock over 14 years
    Workaround here for IE's lack of getComputedStyle erik.eae.net/archives/2007/07/27/18.54.15
  • Pramod Prajapati
    Pramod Prajapati over 12 years
    I'll expand on your second paragraph to explain that only a z-index value of <> 0, and not auto, actually creates a new stacking context.
  • ThatGuy
    ThatGuy over 12 years
    this one seems to be the most shortest and efficient method of getting z-index i've seen so far.
  • manafi
    manafi over 11 years
    Why would you limit it to one element type?
  • user2064000
    user2064000 almost 11 years
    @ChristopherJamesCalo, it is a generic solution. If you use '*' as the argument of findHighestZIndex, it'll get for all elements.
  • 190290000 Ruble Man
    190290000 Ruble Man almost 10 years
    Currently doesn't work properly because highest is saved as string. Instead, set zindex after calling parseInt on the z-index that you've found (note: this means you should check for !isNaN() rather than != 'auto').
  • Sam Eaton
    Sam Eaton about 8 years
    This only works if all z-index are below 999. It is comparing strings so it thinks 999 > 1000. It also assumes that the highest z-index is above zero. It is possible that the highest is a negative number. devmunchies.com/tutorial/finding-highest-z-index-on-page
  • serdar.sanri
    serdar.sanri over 7 years
    Why not to use Math.max() ?
  • ProfK
    ProfK over 6 years
    The only answer I've found that isn't limited to the max for a certain element type. I want my z-index higher that all other z-indexes and this is a gem.
  • Micah Murray
    Micah Murray about 6 years
    While I agree this is a best practice and could help in most situations, it doesn't help if you are building a plugin or script that may run on an unknown page where your script isn't privy to the z-index conventions used. (sorry to comment on your 9-year-old post.)
  • Adam Szmyd
    Adam Szmyd about 6 years
    Sort needs an comparator to work properly. Consider this: [2 ,1, 100].sort() gives in result [1, 100, 2] which is wrong. Use comparator instead: [2 ,1, 100].sort((a,b) => a-b) which gives correct [1, 2, 100]
  • oriadam
    oriadam over 5 years
    elegant but not usable because, from mdn of Math.max: "both spread (...) and apply will either fail or return the wrong result if the array has too many elements"
  • oriadam
    oriadam over 5 years
    using sort seems like a whole lot of unnecessary cpu and memory consumption
  • oriadam
    oriadam over 5 years
    According to MDN one cannot use Math.max to do this: "both spread (...) and apply will either fail or return the wrong result if the array has too many elements [...] The reduce solution does not have this problem"
  • oriadam
    oriadam over 5 years
    Having said that, this will probably cover most real life cases as Chrome supports up to 100k values, Firefox 300k, Edge 400k.
  • oriadam
    oriadam over 5 years
    ^ Having said that, Math.max can accept up to 100,000 arguments on Chrome, 300,000 on Firefox, 400,000 on Edge, 150,000 on IE11 (tested on Win10, all browsers latest).
  • Robert Koritnik
    Robert Koritnik over 4 years
    A reduce would only go through the set of indices once so O = n, while sort has O = n log(n). So one can easily replace sort and pop with reduce.
  • Arsha
    Arsha over 4 years
    This answer itself did not work. Add .sort((a,b) => a-b) as @AdamSzmyd said make it working.
  • justdan23
    justdan23 almost 4 years
    I like using jQuery to ensure compatibility across 22 browsers. I also like @serdar.sanri 's comment to improve it with Math.max().
  • Peter W
    Peter W almost 4 years
    @190290000RubleMan actually the zindex > highest is sufficient to rule out cases where zindex is NaN, because NaN > highest would always return false.
  • AWolf
    AWolf over 3 years
    I'd like to leave my fiddle here. I've also added some tests in the fiddle (not sure if I have covered everything).
  • Tina Hammar
    Tina Hammar about 3 years
    I prefer this way. Slightly modified to cover if "highest" is not NaN. + I wanted to increase by 1 to place my element on top. isNaN(z) || z < highest ? (isNaN(highest) ? 1 : highest + 1) : z
  • podperson
    podperson about 3 years
    I was about to incorporate your extra isNaN check, but upon reflection realised highest is initialized to a number and never set to anything that could be isNaN. if isNaN(z), highest doesn't need to be increased it's already highest. So for every bad z value it would unnecessarily increment highest.
  • Tina Hammar
    Tina Hammar about 3 years
    You need the extra isNaN(z) || z < highest ? (isNaN(highest) ? 1 : highest) : z check because if no z-index is set, to any element in body, highest will be NaN and you will probably want to return at least 1 from the function to be able to use it for element.style.zIndex = findHighestZ().
  • podperson
    podperson almost 3 years
    Ah yes. "auto". Thanks for following up.
  • podperson
    podperson almost 3 years
    The larger bug is the parameters are around the wrong way and the default is overridden :) — so it gets simpler rather than more complex when I flip the comparison because NaN will never be > than an actual value.
  • Daniel Bengtsson
    Daniel Bengtsson almost 3 years
    pretty similar to what I thought as well. Only, a few things I would change: Have 2 variables - one to record the highest (if it's a number) if not, add +1 to a variable. for auto, etc. return highest declared + the counter for all the autos you found. Guarenteed to be the highest.
  • chovy
    chovy over 2 years
    this doesnj't give me the element though. so how can i get the element with the highest z-index?
  • Andrius R.
    Andrius R. over 2 years
    I'm assuming the prefix + is used here instead of parseInt, because it works faster. zIndex can return 'auto', so that gets turned into NaN.
  • Marek Lisiecki
    Marek Lisiecki about 2 years
    first of all in map i recommend to do: parseInt(getComputedStyle(elem).zIndex, 10) || 0, second thing [...document.querySelectorAll('body > *')] - changed selector to body > * it reduces elements to check. As you know, nested elements with z-Index depends of it's parents elemens, so it is not necessary to check them all, you only have to check childs of interesting element - here body
  • podperson
    podperson about 2 years
    I actually don't trust the specified behavior of z-index as described and so this is less efficient and more paranoid.