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

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

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

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

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

还有我可能漏掉的吗?


当前回答

改进了上面@Guy Messika的回答,如果中心点' X < 0是错误的,则中断并返回false,因为元素右侧可能会进入视图。这里有一个解决方案:

private isVisible(elem) {
    const style = getComputedStyle(elem);

    if (style.display === 'none') return false;
    if (style.visibility !== 'visible') return false;
    if ((style.opacity as any) === 0) return false;

    if (
        elem.offsetWidth +
        elem.offsetHeight +
        elem.getBoundingClientRect().height +
        elem.getBoundingClientRect().width === 0
    ) return false;

    const elementPoints = {
        center: {
            x: elem.getBoundingClientRect().left + elem.offsetWidth / 2,
            y: elem.getBoundingClientRect().top + elem.offsetHeight / 2,
        },
        topLeft: {
            x: elem.getBoundingClientRect().left,
            y: elem.getBoundingClientRect().top,
        },
        topRight: {
            x: elem.getBoundingClientRect().right,
            y: elem.getBoundingClientRect().top,
        },
        bottomLeft: {
            x: elem.getBoundingClientRect().left,
            y: elem.getBoundingClientRect().bottom,
        },
        bottomRight: {
            x: elem.getBoundingClientRect().right,
            y: elem.getBoundingClientRect().bottom,
        },
    };

    const docWidth = document.documentElement.clientWidth || window.innerWidth;
    const docHeight = document.documentElement.clientHeight || window.innerHeight;

    if (elementPoints.topLeft.x > docWidth) return false;
    if (elementPoints.topLeft.y > docHeight) return false;
    if (elementPoints.bottomRight.x < 0) return false;
    if (elementPoints.bottomRight.y < 0) return false;

    for (let index in elementPoints) {
        const point = elementPoints[index];
        let pointContainer = document.elementFromPoint(point.x, point.y);
        if (pointContainer !== null) {
            do {
                if (pointContainer === elem) return true;
            } while (pointContainer = pointContainer.parentNode);
        }
    }
    return false;
}

其他回答

这是一种确定所有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属性,非常通用和可靠。

这可能会有帮助: 将元素隐藏在最左边的位置,然后检查offsetLeft属性。如果你想使用jQuery,你可以简单地检查:visible选择器并获得元素的可见状态。

HTML:

<div id="myDiv">Hello</div>

CSS:

<!-- for javaScript-->
#myDiv{
   position:absolute;
   left : -2000px;
}

<!-- for jQuery -->
#myDiv{
    visibility:hidden;
}

javaScript:

var myStyle = document.getElementById("myDiv").offsetLeft;

if(myStyle < 0){
     alert("Div is hidden!!");
}

jQuery:

if(  $("#MyElement").is(":visible") == true )
{  
     alert("Div is visible!!");        
}

js小提琴

我有一个更有效的解决方案相比AlexZ的getComputedStyle()解决方案时,有位置“固定”元素,如果一个愿意忽略一些边缘情况(检查评论):

function isVisible(el) {
    /* offsetParent would be null if display 'none' is set.
       However Chrome, IE and MS Edge returns offsetParent as null for elements
       with CSS position 'fixed'. So check whether the dimensions are zero.

       This check would be inaccurate if position is 'fixed' AND dimensions were
       intentionally set to zero. But..it is good enough for most cases.*/
    return Boolean(el.offsetParent || el.offsetWidth || el.offsetHeight);
}

附注:严格来说,“可见性”首先需要定义。在我的情况下,我正在考虑一个元素可见,只要我可以运行所有DOM方法/属性上没有问题(即使不透明度为0或CSS可见性属性是“隐藏”等)。

下面是一个(纯纯的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;
}

Chrome 105(以及Edge和Opera)和Firefox 106引入了element . checkvisibility(),如果元素是可见的,则返回true,否则返回false。

该函数检查了使元素不可见的各种因素,包括display:none、可见性、内容可见性和不透明度:

let element = document.getElementById("myIcon");
let isVisible = element.checkVisibility({
    checkOpacity: true,      // Check CSS opacity property too
    checkVisibilityCSS: true // Check CSS visibility property too
});

旁注:checkVisibility()以前被称为isVisible()。看这个GitHub问题。 参见这里的checkVisibility()规范草案。