有什么方法,我可以检查如果一个元素是可见的纯JS(没有jQuery) ?

因此,给定一个DOM元素,我如何检查它是否可见?我试着:

window.getComputedStyle(my_element)['display']);

但这似乎并不奏效。我想知道我应该检查哪些属性。我想到了:

display !== 'none'
visibility !== 'hidden'

还有我可能漏掉的吗?


当前回答

下面是一个(纯纯的JS)函数,它执行大量的检查,确保给定的元素对用户可见:

function isVisible(element) {
    // Check if the element is null or undefined
    if (!element) return false;

    // Get the element's bounding client rect
    const boundingRect = element.getBoundingClientRect();

    // Check if the element has a positive width and height
    if (boundingRect.width <= 0 || boundingRect.height <= 0) return false;

    // Check if the element's top and left values are within the viewport
    const top = boundingRect.top;
    const left = boundingRect.left;
    const viewportWidth = window.innerWidth || document.documentElement.clientWidth;
    const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
    if (top > viewportHeight || left > viewportWidth) return false;

    // Check if the element's right and bottom values are within the viewport
    const right = boundingRect.right;
    const bottom = boundingRect.bottom;
    if (right < 0 || bottom < 0) return false;

    // Check if the element is hidden by the overflow property
    const parentNode = element.parentNode;
    if (parentNode && getComputedStyle(parentNode).overflow === 'hidden') {
        const parentRect = parentNode.getBoundingClientRect();
        if (top < parentRect.top || bottom > parentRect.bottom || left < parentRect.left || right > parentRect.right) {
            return false;
        }
    }

    const elementComputedStyle = getComputedStyle(element);

    // Check if the element has a z-index of less than 0
    const zIndex = elementComputedStyle.zIndex;
    if (zIndex < 0) return false;

    // Check if the element has a display value of 'none' or an opacity of 0
    const display = elementComputedStyle.display;
    const opacity = elementComputedStyle.opacity;
    if (display === 'none' || opacity === '0') return false;

    // Check if the element is hidden by an ancestor element with a display value of 'none' or an opacity of 0
    let ancestorElement = element.parentElement;
    while (ancestorElement) {
        const ancestorComputedStyle = getComputedStyle(ancestorElement);
        const ancestorDisplay = ancestorComputedStyle.display;
        const ancestorOpacity = ancestorComputedStyle.opacity;
        if (ancestorDisplay === 'none' || ancestorOpacity === '0') return false;
        ancestorElement = ancestorElement.parentElement;
    }

    // Initialize a variable to keep track of whether the element is obscured by another element
    let obscured = false;

    // Check if the element is obscured by another element according to its position
    if (elementComputedStyle.position === 'absolute' || elementComputedStyle.position === 'fixed' ||
        elementComputedStyle.position === 'relative' || elementComputedStyle.position === 'sticky' ||
        elementComputedStyle.position === 'static') {
        let siblingElement = element.nextElementSibling;
        while (siblingElement) {
            if (siblingElement.getBoundingClientRect().top > boundingRect.bottom || siblingElement.getBoundingClientRect().left > boundingRect.right) {
                break;
            }
            if (siblingElement.getBoundingClientRect().bottom > boundingRect.top && siblingElement.getBoundingClientRect().right > boundingRect.left) {
                obscured = true;
                break;
            }
            siblingElement = siblingElement.nextElementSibling;
        }
        if (obscured) return false;
    }

    // If all checks have passed, the element is visible
    return true;
}

其他回答

结合上面的几个答案:

function isVisible (ele) {
    var style = window.getComputedStyle(ele);
    return  style.width !== "0" &&
    style.height !== "0" &&
    style.opacity !== "0" &&
    style.display!=='none' &&
    style.visibility!== 'hidden';
}

就像AlexZ说的,这可能会比你的一些其他选择更慢,如果你更具体地知道你在寻找什么,但这应该抓住所有隐藏元素的主要方式。

但是,这也取决于你认为什么是可见的。例如,一个div的高度可以设置为0px,但内容仍然可见,这取决于溢出属性。或者,可以将div的内容设置为与背景相同的颜色,这样用户就不会看到它,但仍然可以在页面上显示。或者一个div可以移出屏幕或隐藏在其他div后面,或者它的内容可以是不可见的,但边界仍然可见。在一定程度上,“可见”是一个主观术语。

这是一种确定所有css属性(包括可见性)的方法:

html:

<div id="element">div content</div>

css:

#element
{
visibility:hidden;
}

javascript:

var element = document.getElementById('element');
 if(element.style.visibility == 'hidden'){
alert('hidden');
}
else
{
alert('visible');
}

它适用于任何css属性,非常通用和可靠。

这就是我所做的:

HTML和CSS:默认情况下使元素隐藏

<html>
<body>

<button onclick="myFunction()">Click Me</button>

<p id="demo" style ="visibility: hidden;">Hello World</p> 

</body>
</html> 

JavaScript:增加了一个代码来检查可见性是否被隐藏:

<script>
function myFunction() {
   if ( document.getElementById("demo").style.visibility === "hidden"){
   document.getElementById("demo").style.visibility = "visible";
   }
   else document.getElementById("demo").style.visibility = "hidden";
}
</script>

公认的答案对我不起作用。

2020年分解。

The (elem.offsetParent !== null) method works fine in Firefox but not in Chrome. In Chrome position: fixed will also make offsetParent return null even the element if visible in the page. User Phrogz conducted a large test (2,304 divs) on elements with varying properties to demonstrate the issue. https://stackoverflow.com/a/11639664/4481831 . Run it with multiple browsers to see the differences. Demo: //different results in Chrome and Firefox console.log(document.querySelector('#hidden1').offsetParent); //null Chrome & Firefox console.log(document.querySelector('#fixed1').offsetParent); //null in Chrome, not null in Firefox <div id="hidden1" style="display:none;"></div> <div id="fixed1" style="position:fixed;"></div> The (getComputedStyle(elem).display !== 'none') does not work because the element can be invisible because one of the parents display property is set to none, getComputedStyle will not catch that. Demo: var child1 = document.querySelector('#child1'); console.log(getComputedStyle(child1).display); //child will show "block" instead of "none" <div id="parent1" style="display:none;"> <div id="child1" style="display:block"></div> </div> The (elem.clientHeight !== 0). This method is not influenced by position: fixed and it also check if element parents are not-visible. But it has problems with simple elements that do not have a css layout and inline elements, see more here Demo: console.log(document.querySelector('#inline1').clientHeight); //zero console.log(document.querySelector('#div1').clientHeight); //not zero console.log(document.querySelector('#span1').clientHeight); //zero <div id="inline1" style="display:inline">test1 inline</div> <div id="div1">test2 div</div> <span id="span1">test3 span</span> The (elem.getClientRects().length !== 0) may seem to solve the problems of the previous 3 methods. However it has problems with elements that use CSS tricks (other then display: none) to hide in the page. Demo console.log(document.querySelector('#notvisible1').getClientRects().length); console.log(document.querySelector('#notvisible1').clientHeight); console.log(document.querySelector('#notvisible2').getClientRects().length); console.log(document.querySelector('#notvisible2').clientHeight); console.log(document.querySelector('#notvisible3').getClientRects().length); console.log(document.querySelector('#notvisible3').clientHeight); <div id="notvisible1" style="height:0; overflow:hidden; background-color:red;">not visible 1</div> <div id="notvisible2" style="visibility:hidden; background-color:yellow;">not visible 2</div> <div id="notvisible3" style="opacity:0; background-color:blue;">not visible 3</div>

结论。

所以我向你们展示的是没有什么方法是完美的。要进行适当的可见性检查,必须结合使用后3种方法。

来自http://code.jquery.com/jquery-1.11.1.js的jQuery代码有一个isHidden参数

var isHidden = function( elem, el ) {
    // isHidden might be called from jQuery#filter function;
    // in that case, element will be second argument
    elem = el || elem;
    return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
};

因此,看起来有一个与所有者文档相关的额外检查

我想知道这是否真的适用于以下情况:

基于zIndex隐藏在其他元素后面的元素 完全透明的元素使它们不可见 位于屏幕外的元素(即左:-1000px) 具有可见性的元素:隐藏 有显示的元素:无 没有可见文本或子元素的元素 高度或宽度设置为0的元素