如何找出文档中最高的z索引?


73

为了将包含透明文本图像的div设置为文档中的最高z索引,我选择了10,000,它解决了我的问题。

以前我猜过数字3,但没有效果。

因此,是否有更科学的方法来确定哪个z索引比您所有其他元素的z索引高?

我尝试在Firebug中寻找此指标,但找不到。


请注意,找到最大的z-index并不完全相关,但可以使用。您需要的是构成堆叠上下文的那些元素中最大的z-index,这些元素与您要放置的元素位于同一堆叠上下文中。换句话说,如果找到的元素position: relative; z-index: 10000;位于的元素之内position: relative; z-index: 100;,则您需要击败的数字是100,而不是10,000。
克里斯·卡洛

Answers:


37

您可以像这样调用findHighestZIndex特定的元素类型<div>

findHighestZIndex('div');

假设findHighestZindex函数定义如下:

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;
}

IE缺少getComputedStyle的解决方法erik.eae.net/archives/2007/07/27/18.54.15
Matthew Lock 2009年

为什么将其限制为一种元素类型?
克里斯·卡洛

1
@ChristopherJamesCalo,这是一个通用解决方案。如果使用'*'作为的参数findHighestZIndex,它将获得所有元素。
user2064000

当前无法正常工作,因为最高级别另存为字符串。而是在找到的z-index上调用parseInt之后设置zindex(注意:这意味着您应该检查!isNaN()而不是!='auto')。
190290000卢布人2014年

1
仅当所有z索引均低于999时,此方法才有效。它正在比较字符串,因此认为999>1000。它还假定最高z索引高于零。最高可能是负数。devmunchies.com/tutorial/finding-highest-z-index-on-page
山姆·伊顿

44

为了清楚起见,从abcoder站点窃取了一些代码:

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

到目前为止,这似乎是获得z-index的最短,最有效的方法。
ThatGuy

我发现的唯一答案并不限于特定元素类型的最大值。我希望我的z-index高于所有其他z-index,这是一颗宝石。
ProfK

1
优雅但无法使用,因为来自mdn的Math.max:“如果数组包含太多元素,两者都会传播(...)apply否则将失败或返回错误的结果”
oriadam

2
^话虽如此,Math.max在Chrome上最多可以接受100,000个参数,在Firefox上可以接受300,000个参数,在Edge上可以接受400,000个参数,在IE11上可以接受150,000个参数(在Win10上经过测试,所有浏览器都是最新的)。
oriadam

14

使用ES6更清洁的方法

function maxZIndex() {

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

5
排序需要一个比较器才能正常工作。考虑一下:[2 ,1, 100].sort()给出结果[1, 100, 2]错误的。请改用比较器:[2 ,1, 100].sort((a,b) => a-b)这样比较正确[1, 2, 100]
Adam Szmyd

4
使用 sort似乎有很多不必要的cpu​​和内存消耗
oriadam

2
一个reduce只会通过索引集去一次这样O = n,尽管sortO = n log(n)。因此,人们可以很容易地更换sortpop使用reduce
罗伯特·科里特尼克'19

这个答案本身没有用。添加.sort((a,b) => a-b)为@AdamSzmyd说使它工作。
VEE

5

我想添加在一个UserScript中使用的ECMAScript 6实现。我正在使用这一z-index元素来定义特定元素,以使它们始终显示为最高。我可以使用链接的:not选择器排除这些元素。

let highestZIndex = 0;

// 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))
);

较低的五行可以运行多次,并highestZIndex通过找出当前行之间的最大值来重复更新变量 highestZIndex值与所有元素的所有其他计算的z索引。在filter排除所有的"auto"值。


根据MDN一个不能使用Math.max要做到这一点:“既传播(...)apply要么失败或返回错误的结果,如果数组有太多元素[...]将降低解决方案不存在这个问题”
oriadam

话虽如此,这可能会涵盖大多数现实生活中的情况,因为Chrome支持多达100k的值,Firefox 300k,Edge 400k。
oriadam '18

4

在我看来,解决此问题的最佳方法是为自己设定约定,以将z-index不同类型的元素用于不同类型的元素。然后,z-index通过回顾文档,您将找到正确的使用方法。


1
虽然我同意这是一种最佳做法,并且在大多数情况下可能会有所帮助,但是如果您构建的插件或脚本可能在未知页面上运行,而您的脚本并不依赖于所使用的z-index约定,那么这将无济于事。(很抱歉对您9岁的帖子发表评论。)
Micah Murray

4

我相信您正在观察的是Voodoo。如果没有访问您完整的样式表,我当然不能可靠地告诉您。但令我惊讶的是,这里真正发生的事情是您忘记了只有定位元素会受到的影响z-index

此外,z-indexes不会自动分配,仅在样式表中分配,这意味着在没有其他z-indexed元素的情况下,esz-index:1;将排在其他所有东西之上。


我将在您的第二段内容中进行扩展,以说明仅z-index<> 0而不是值auto实际上会创建一个新的堆栈上下文。
凯文·佩诺

4

我想你必须自己做...

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;
}

3
当然,除了可以定位和z索引之外,任何元素都可以定位,而不仅仅是div。
Williham Totland

5
问题是,element.style.zIndex找不到在外部样式表中设置的z索引。谷歌getComputedStyle寻找那些。
Boldewyn

4

没有默认属性或其他任何属性,但是您可以编写一些JavaScript来遍历所有元素并将其找出来。或者,如果您使用jQuery之类的DOM管理库,则可以扩展其方法(或查找其是否已支持),以便它开始从页面加载中跟踪元素z索引,然后检索最高的z-变得很简单。指数。


2

使用jQuery:

如果未提供任何元素,则检查所有元素。

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;
}

为什么不使用Math.max()?
serdar.sanri,2017年

我喜欢使用jQuery确保22个浏览器之间的兼容性。我也喜欢@ serdar.sanri的注释,以使用Math.max()对其进行改进。
justdan23 '20

1

我最近不得不为一个项目执行此操作,发现从@Philippe Gerber的出色答案和@flo的出色答案(已接受的答案)中受益匪浅

与上述参考答案的主要区别在于:

  • CSSz-index和任何内联z-index样式都将被计算,并使用两者中较大的一个进行比较和计算。
  • 值被强制成整数,任何字符串值(autostatic,等)将被忽略。

是代码示例的CodePen,但也包含在此处。

(() => {
  /**
   * 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>


1

Array.reduce()

这里是另一种解决方案,以确定最上面的z-index使用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)

1

在NodeList中找到最大zIndex的强大解决方案

  1. 您应该同时检查getComputedStylestyle对象由节点本身提供
  2. 使用Number.isNaN代替isNaN是因为 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 *"));

我想把我的小提琴留在这里。我还在小提琴中添加了一些测试(不确定是否涵盖了所有内容)。
AWolf

1

ShadowRoot解决方案

我们一定不要忘记自定义元素和影子根目录内容。

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;
}


1

上面的“ ES6”版本比第一个解决方案效率低,因为它在整个阵列上进行了多次冗余传递。而是尝试:

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

从理论上讲,在一个减少的步骤中执行此操作甚至会更快,但是一些快速基准测试没有明显区别,并且代码更加粗糙


0

如果要显示具有最高z索引的所有元素的ID

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)
}

用法

show_highest_z()

结果

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

0

一个受@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>

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.