6

The question couldn't be easier. The z-index values are assigned by style=... or className, with Javascript or not. I don't think it matters. How do I find (with Javascript) the highest z-index? (The element it's used in would be nice, but not necessary.)

You can't use the (new) querySelector, because it doesn't query CSS values. Is there someway to query CSS? (Not the stylesheets, but the actual used values.)

Grazi


Get top 5 elements + z-indexes:

Array.from(document.querySelectorAll('*')).map(el => [el, getComputedStyle(el).zIndex]).filter(v => !isNaN(parseInt(v[1]))).sort((a, b) => b[1] - a[1]).slice(0, 5)
Rudie
  • 52,220
  • 42
  • 131
  • 173
  • Duplicate: http://stackoverflow.com/questions/1118198/how-can-you-figure-out-the-highest-z-index-in-your-document – Evan Mulawski Dec 21 '10 at 21:20
  • I would use PHP Simple HTML DOM for this and you can even edit values of elements, their attributes and so on then save it back to the file or another file etc and return the data in json to your javascript to update whatever element your sHTMLdom returned... You could also return a list of elements that have a z-index "style" attribute set and order them based off of their value resulting in the answer to your question. – Gregory Bowers Dec 29 '20 at 05:19
  • 10 years later LOL – Gregory Bowers Dec 29 '20 at 05:23

5 Answers5

16

It's not as simple as finding the element with the highest z-index. Stacking order also depends on tree relationship, so if a static positioned element with the most z-index explicitly set, and if your code retrieved that, it would be useless since z-index is useless on static positioned elements.

In addition, IE's stacking order rules are completely broken so you would have to account for that as well. And you may have to account for iframe/select elements in IE pre 8/9 since they have more stacking order priority than any other nodes.

This would probably be useful: http://www.w3.org/TR/CSS21/zindex.html

You'd have to follow all of those and account for IE bugs in order to have a consistent method of getting the element with the most stacking order priority.

meder omuraliev
  • 183,342
  • 71
  • 393
  • 434
  • Agree with Matt - I had completely forgotten some of those other issues. – Charles Boyung Dec 21 '10 at 21:26
  • Actually it is as simple as finding the (element with) the highest z-index, because that was my question. But thanks for the elaborate response. – Rudie Dec 23 '10 at 08:19
  • I would disagree that it not as simple as finding the element with the highest z-index value. For example, if I wanted to load html from random files that are generated by a program that i created that i know have a hierarchy index value waiting to tell me which order to put the elements on top of each other.. Sorry i'm a little late, its crazy how old problems can still be new problems. To solve this I ended up using PHP Simple HTML Dom as it allows you to load CSS stylesheets or exclude them. basically the result is processed styles that you can query and alter. – Gregory Bowers Dec 29 '20 at 05:28
4

This is a modified version of kennebec's/Pravens code which finds the highest z-index within a stacking context. This version also takes opacity into account.

If all you're looking for is to position an element on top of everything else in the page, simply call highZ(document.body) or just highZ(). It finds the highest z-index of the root stacking context which will do exactly that.

  • Only non-statically positioned elements matter within a stacking context.
  • Elements that are not positioned do not start a new stacking context. So their descendents may exist in the current stacking context. Hence the recursion.
  • Also, if the z-index is 'auto', the element does not start a new stacking context, so you must recurse through its elements.
  • elements with an opacity value less than 1 start a new stacking context. If an element with opacity less than 1 is not positioned, implementations must paint the layer it creates, within its parent stacking context, at the same stacking order that would be used if it were a positioned element with ‘z-index: 0’ and ‘opacity: 1’. If an element with opacity less than 1 is positioned, the ‘z-index’ property applies as described in [CSS21], except that ‘auto’ is treated as ‘0’ since a new stacking context is always created.

    function highZ(parent, limit){
        limit = limit || Infinity;
        parent = parent || document.body;
        var who, temp, max= 1, opacity, i= 0;
        var children = parent.childNodes, length = children.length;
        while(i<length){
            who = children[i++];
            if (who.nodeType != 1) continue; // element nodes only
            opacity = deepCss(who,"opacity");
            if (deepCss(who,"position") !== "static") {
                temp = deepCss(who,"z-index");
                if (temp == "auto") { // positioned and z-index is auto, a new stacking context for opacity < 0. Further When zindex is auto ,it shall be treated as zindex = 0 within stacking context.
                    (opacity < 1)? temp=0:temp = highZ(who);
                } else {
                    temp = parseInt(temp, 10) || 0;
                }
            } else { // non-positioned element, a new stacking context for opacity < 1 and zindex shall be treated as if 0
                (opacity < 1)? temp=0:temp = highZ(who);
            }
            if (temp > max && temp <= limit) max = temp;                
        }
        return max;
    }
    
    function deepCss(who, css) {
        var sty, val, dv= document.defaultView || window;
        if (who.nodeType == 1) {
            sty = css.replace(/\-([a-z])/g, function(a, b){
                return b.toUpperCase();
            });
            val = who.style[sty];
            if (!val) {
                if(who.currentStyle) val= who.currentStyle[sty];
                else if (dv.getComputedStyle) {
                    val= dv.getComputedStyle(who,"").getPropertyValue(css);
                }
            }
        }
        return val || "";
    }
    
Zahoor
  • 48
  • 5
Praveen
  • 331
  • 4
  • 15
  • Nice. I noticed your answer after commenting on the one you "fixed". Sad that your's is way down here. The only thing I would note is that, while positioning can create a new stack, other factors affect the stack as well (static[block before float before inline] before positioned ordered by z-index) and that a negative `z-index` makes things even more fun... – Kevin Peno Aug 19 '11 at 19:16
2

You would need to loop through every single element in the DOM and keep track of the max z-index found as you loop, along with the element that has that z-index. Then, when you are done, you will have the element you are looking for.

This is an incredibly intensive piece of script and could kill your users' browsers. Why in the world would you want to do this?

Charles Boyung
  • 2,464
  • 1
  • 21
  • 31
2

You only need sibling elements to find the highest z-index, so start with a parent element or the body.

And often you have some element with a really high z-index that you want to be always on top- if so, ignore z indexes over a million or whatever is safely above the number of siblings.

You can do it in one function, but the syntax for finding stylesheet values is handy to have around.

function highZ(pa, limit){
    limit= limit || Infinity;
    pa= pa || document.body;
    var who, tem, mx= 1, A= [], i= 0, L;
    pa= pa.childNodes, L= pa.length;
    while(i<L){
        who= pa[i++]
        if(who.nodeType== 1){
            tem= parseInt(deepCss(who,"z-index")) || 0;
            if(tem> mx && tem<=limit) mx= tem;
        }
    }
    return mx;
}
function deepCss(who, css){
    var sty, val, dv= document.defaultView || window;
    if(who.nodeType== 1){
        sty= css.replace(/\-([a-z])/g, function(a, b){
            return b.toUpperCase();
        });
        val= who.style[sty];
        if(!val){
            if(who.currentStyle) val= who.currentStyle[sty];
            else if(dv.getComputedStyle){
                val= dv.getComputedStyle(who,"").getPropertyValue(css);
            }
        }
    }
    return val || "";
}

alert(highZ())

kennebec
  • 102,654
  • 32
  • 106
  • 127
  • Unfortunately this just isn't true. Siblings may have different stacking orders based on the context of their parents, yes. However, 3 siblings can have a number of different stacking order schemes depending on a lot of factors related to the layout rules. – Kevin Peno Aug 19 '11 at 18:56
  • Example: the parent is `position: absolute`, so stacking order of children always starts within it. Sib1 is positioned, sib2 is inline, sib3 is floated. No sib declares `z-index`. The stack is Sib3, Sib2, Sib1. In your code you will get the stack of Sib1, Sib2, Sib3. – Kevin Peno Aug 19 '11 at 18:56
  • Example 2: Same as above with z-index applied (even in error). Sib1 is `z-index -1`, Sib2 is `z-index: auto`, Sib3 is `z-index: 1`. The result of the stack should be: Sib1, Sib3, Sib2. This is because `float` doesn't effect `position` which is required for `z-index` to apply. Your function will give the same as previous: Sib1, Sib2, Sib3. – Kevin Peno Aug 19 '11 at 19:02
-4

meder makes a great point! I tried to code it anyway, because I'm bored at work and can't help myself:

NOTE: Will only work on style set using the style attribute (won't capture style set by stylesheets)

function getHighIndex (selector) {
    if (!selector) { selector = "*" };

    var elements = document.querySelectorAll(selector) ||
                   oXmlDom.documentElement.selectNodes(selector),
        i = 0,
        e, s,
        max = elements.length,
        found = [];

    for (; i < max; i += 1) {
        e = elements[i].style.zIndex;
        s = elements[i].style.position;
        if (e && s !== "static") {
          found.push(parseInt(e, 10));
        }
    }

    return found.length ? Math.max.apply(null, found) : 0;
}
Kai
  • 9,038
  • 5
  • 28
  • 28
  • 2
    This won't get any z-index set in a stylesheet (as opposed to a style attribute). – Quentin Dec 21 '10 at 21:53
  • Correct, and I'll add that as a disclaimer! – Kai Dec 21 '10 at 21:56
  • Wouldn't `document.getElementsByTagName('*')` be easier on the DOM? And maybe start at the end because that's usually where the high z-indexes are. I'm not looking for in-stylesheet defined z-indexes; only for applied z-indexes (so in elements). – Rudie Dec 23 '10 at 08:21
  • This will work: `NodeList.prototype.map = function(fn) { var a=[]; for ( var i=0; i – Rudie Dec 23 '10 at 17:38
  • @Rudie - not sure why you accepted this answer, since it clearly doesn't answer your question - you wanted to get the z-index across all styles, including styles set via class name, which this won't do. – Charles Boyung Dec 27 '10 at 18:37
  • @Charles Boyung See Rudie's comment in reply to meder's answer; he was satisfied with element-level zIndex search. He then accepted my answer and also commented with a JS snippet that does a similar element-level search. Clearly, my answer helped him. Thanks for the downvote? :-| – Kai Dec 28 '10 at 16:12
  • Charles, you're right. Instead of `.style` I'd have to use `.getCalculatedStyle()` or something. But now it's too late to take it back =) – Rudie Dec 31 '10 at 01:40
  • @Rudie, since when are elements ordered in the DOM by `z-index`? It is true that an intrinsically static elements are ordered into the stack reverse the order they are declared in the source, but `z-index` plays no role in the DOM. – Kevin Peno Aug 19 '11 at 18:49
  • @Kevin Peno Who says DOM elements are ordered by `z-index`..? – Rudie Aug 19 '11 at 20:09
  • @Rudie, you in the third comment: `..and maybe start at the end because that's usually where the high z-indexes are.` – Kevin Peno Aug 19 '11 at 20:36
  • @Kevin Well, aren't they? I usually create web pages so elements that should be on top are on the end of the DOM (overlays, notices, highlights etc). It's really not relevant though... – Rudie Aug 20 '11 at 09:56
  • @Rudie, I'd suggest you read this article. http://timkadlec.com/2008/01/detailed-look-at-stacking-in-css/ – Kevin Peno Aug 20 '11 at 15:13
  • @Kevin I'm not at all interested in stacking in CSS. (And I know how it works.) As you can see in the question, I was looking for the highest `z-index`. That's it. The highest. Not stacking order or display or (a combination of) other properties. Just the highest `z-index`. `position` has nothing to do with that. Why is everybody talking about stacking order!? – Rudie Aug 21 '11 at 01:14
  • @Rudie, I posted that article because of your "understanding" that higher `z-index` is at the bottom of the DOM. **You** might do it that way, but this is not normally the case. – Kevin Peno Aug 22 '11 at 17:22