ChatGPT解决这个技术问题 Extra ChatGPT

检查元素在 DOM 中是否可见

有什么方法可以检查一个元素在纯 JS(没有 jQuery)中是否可见?

那么,给定一个 DOM 元素,我如何检查它是否可见?我试过了:

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

但它似乎没有工作。我想知道我应该检查哪些属性。我想到了:

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

还有其他我可能会想念的吗?

那不使用显示,它使用可见性,因此检查可见性(隐藏或可见)。例如:document.getElementById('snDealsPanel').style.visibility
PSL。如果我想更一般地执行此操作,我应该检查哪些属性:可见性、显示...?
您可以以自己的方式使其通用,但我要说的是它使用可见性检查元素。
这是我针对这个问题的代码(没有 jquery)stackoverflow.com/a/22969337/2274995
链接已损坏,这使您的问题不易理解。请重新构图。

7
7ochem

根据 this MDN documentation,只要元素或其任何父元素通过 display 样式属性隐藏,它的 offsetParent 属性就会返回 null。只要确保元素没有固定。如果您的页面上没有 position: fixed; 元素,则检查此内容的脚本可能如下所示:

// Where el is the DOM element you'd like to test for visibility
function isHidden(el) {
    return (el.offsetParent === null)
}

另一方面,如果您确实有可能在此搜索中被捕获的位置固定元素,那么您将遗憾地(并且慢慢地)不得不使用 window.getComputedStyle()。这种情况下的功能可能是:

// Where el is the DOM element you'd like to test for visibility
function isHidden(el) {
    var style = window.getComputedStyle(el);
    return (style.display === 'none')
}

选项 #2 可能更简单一些,因为它考虑了更多的边缘情况,但我敢打赌它也会慢很多,所以如果你必须多次重复这个操作,最好避免它。


另外仅供参考,刚刚发现 el.offsetParent 不适用于 IE9 的非固定元素。反正看起来是这样。 (不过,对于 IE11 来说还可以。)毕竟是 getComputedStyle
唉! getComputedStyle 不能正常工作:plnkr.co/edit/6CSCA2fe4Gqt4jCBP2wu?p=preview 但是,offsetParent 也是如此 - 也许应该使用两者的组合?
对于 ie9+ie10,您可以检查 offsetParent = body 是否为不可见元素。
我看到 getComputedStyle(element).display 在其祖先为 display:none 的某些元素(例如 TABLE 元素)中具有 table 的值基本上是无用的。
只是关于 window.getComputedStyle 方法的注释,它返回一个实时的 CSSStyleDeclaration 对象。所以你只需要抓取一次样式,然后如果你必须执行多次检查,可以重新检查对象。
g
guy mograbi

对于我来说,所有其他解决方案都因某种情况而崩溃..

请参阅以下位置的获胜答案:

http://plnkr.co/edit/6CSCA2fe4Gqt4jCBP2wu?p=preview

最终,我决定最好的解决方案是 $(elem).is(':visible') - 但是,这不是纯 javascript。这是jquery ..

所以我偷看了他们的来源,找到了我想要的

jQuery.expr.filters.visible = function( elem ) {
    return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
};

这是来源:https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js


这将为具有 visibility:hidden 的元素返回 true
@YuvalA .:是的,因为该元素仍然可见。将元素设置为 visibility:hidden 不再显示任何内容,但仍采用元素的宽度和高度!
OP 要求没有 jQuery 的解决方案
对于寻找同样适用于 visibility:hidden 的版本的任何人,将 && window.getComputedStyle(elem).visibility !== "hidden" 添加到此返回行的末尾似乎有效
@DougWilhelm 这就是显示源代码的原因。源代码是纯 javascript,因为 jQuery 在这个地方不使用其他库。
O
Ohad Navon

如果您对用户可见的感兴趣:

function isVisible(elem) {
    if (!(elem instanceof Element)) throw Error('DomUtil: elem is not an element.');
    const style = getComputedStyle(elem);
    if (style.display === 'none') return false;
    if (style.visibility !== 'visible') return false;
    if (style.opacity < 0.1) return false;
    if (elem.offsetWidth + elem.offsetHeight + elem.getBoundingClientRect().height +
        elem.getBoundingClientRect().width === 0) {
        return false;
    }
    const elemCenter   = {
        x: elem.getBoundingClientRect().left + elem.offsetWidth / 2,
        y: elem.getBoundingClientRect().top + elem.offsetHeight / 2
    };
    if (elemCenter.x < 0) return false;
    if (elemCenter.x > (document.documentElement.clientWidth || window.innerWidth)) return false;
    if (elemCenter.y < 0) return false;
    if (elemCenter.y > (document.documentElement.clientHeight || window.innerHeight)) return false;
    let pointContainer = document.elementFromPoint(elemCenter.x, elemCenter.y);
    do {
        if (pointContainer === elem) return true;
    } while (pointContainer = pointContainer.parentNode);
    return false;
}

测试(使用 mocha 术语):

describe.only('visibility', function () {
    let div, visible, notVisible, inViewport, leftOfViewport, rightOfViewport, aboveViewport,
        belowViewport, notDisplayed, zeroOpacity, zIndex1, zIndex2;
    before(() => {
        div = document.createElement('div');
        document.querySelector('body').appendChild(div);
        div.appendChild(visible = document.createElement('div'));
        visible.style       = 'border: 1px solid black; margin: 5px; display: inline-block;';
        visible.textContent = 'visible';
        div.appendChild(inViewport = visible.cloneNode(false));
        inViewport.textContent = 'inViewport';
        div.appendChild(notDisplayed = visible.cloneNode(false));
        notDisplayed.style.display = 'none';
        notDisplayed.textContent   = 'notDisplayed';
        div.appendChild(notVisible = visible.cloneNode(false));
        notVisible.style.visibility = 'hidden';
        notVisible.textContent      = 'notVisible';
        div.appendChild(leftOfViewport = visible.cloneNode(false));
        leftOfViewport.style.position = 'absolute';
        leftOfViewport.style.right = '100000px';
        leftOfViewport.textContent = 'leftOfViewport';
        div.appendChild(rightOfViewport = leftOfViewport.cloneNode(false));
        rightOfViewport.style.right       = '0';
        rightOfViewport.style.left       = '100000px';
        rightOfViewport.textContent = 'rightOfViewport';
        div.appendChild(aboveViewport = leftOfViewport.cloneNode(false));
        aboveViewport.style.right       = '0';
        aboveViewport.style.bottom       = '100000px';
        aboveViewport.textContent = 'aboveViewport';
        div.appendChild(belowViewport = leftOfViewport.cloneNode(false));
        belowViewport.style.right       = '0';
        belowViewport.style.top       = '100000px';
        belowViewport.textContent = 'belowViewport';
        div.appendChild(zeroOpacity = visible.cloneNode(false));
        zeroOpacity.textContent   = 'zeroOpacity';
        zeroOpacity.style.opacity = '0';
        div.appendChild(zIndex1 = visible.cloneNode(false));
        zIndex1.textContent = 'zIndex1';
        zIndex1.style.position = 'absolute';
        zIndex1.style.left = zIndex1.style.top = zIndex1.style.width = zIndex1.style.height = '100px';
        zIndex1.style.zIndex = '1';
        div.appendChild(zIndex2 = zIndex1.cloneNode(false));
        zIndex2.textContent = 'zIndex2';
        zIndex2.style.left = zIndex2.style.top = '90px';
        zIndex2.style.width = zIndex2.style.height = '120px';
        zIndex2.style.backgroundColor = 'red';
        zIndex2.style.zIndex = '2';
    });
    after(() => {
        div.parentNode.removeChild(div);
    });
    it('isVisible = true', () => {
        expect(isVisible(div)).to.be.true;
        expect(isVisible(visible)).to.be.true;
        expect(isVisible(inViewport)).to.be.true;
        expect(isVisible(zIndex2)).to.be.true;
    });
    it('isVisible = false', () => {
        expect(isVisible(notDisplayed)).to.be.false;
        expect(isVisible(notVisible)).to.be.false;
        expect(isVisible(document.createElement('div'))).to.be.false;
        expect(isVisible(zIndex1)).to.be.false;
        expect(isVisible(zeroOpacity)).to.be.false;
        expect(isVisible(leftOfViewport)).to.be.false;
        expect(isVisible(rightOfViewport)).to.be.false;
        expect(isVisible(aboveViewport)).to.be.false;
        expect(isVisible(belowViewport)).to.be.false;
    });
});

如果元素位于视口之外,则边缘情况可以被“if (!pointContainer) return false;”捕获。检查第一个点容器
如果您想检查用户是否可以看到它,您必须使用 scrollIntoView 对吗?!这是相当昂贵的。还有其他聪明的方法吗?
当重叠元素(准确地说:所有重叠元素)的不透明度 < 1 时会怎样?
救生员。 js就是这样的……语言
Y
Yvan

使用与 jQuery 相同的代码:

jQuery.expr.pseudos.visible = function( elem ) {
    return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
};

所以,在一个函数中:

function isVisible(e) {
    return !!( e.offsetWidth || e.offsetHeight || e.getClientRects().length );
}

在我的 Win/IE10、Linux/Firefox.45、Linux/Chrome.52...

非常感谢没有 jQuery 的 jQuery!


很好,但不包括被溢出隐藏的元素。
很好,但为什么! (双重否定)?
将结果强制为布尔值。由于 e.offsetWidth 是一个整数,如果 e.offsetWidth 大于零(元素可见),!e.offsetWidth 将返回 false。因此,如果 e.offsetWidth 大于零,则在 !!e.offsetWidth 中添加另一个 ! 将返回 true。它是 return e.offsetWidth > 0 ? true : false 或显然是 return e.offsetWidth > 0 的简写。
因此,如果我想要一个“isHidden”函数,我会使用单个 ! 而不是 !!
@Jarad 你是对的 :-) 双 !! 用于强制结果为布尔值。但是,正如您想要相反的那样,只需要一个。
H
Harry B

这可能会有所帮助: 通过将元素定位在最左侧位置来隐藏元素,然后检查 offsetLeft 属性。如果您想使用 jQuery,您只需检查 :visible 选择器并获取元素的可见性状态。

HTML:

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

CSS:

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

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

脚本:

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

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

jQuery :

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

jsFiddle


OP 要求一个没有 jQuery 的答案。
我猜它后来被编辑了。当我回答时,线程中没有提到它。
@StephenQuan,我已经用 jQuery 和 javaScript 解决方案更新了答案。
对于 jQuery 示例,警报不应该说“Div 可见吗?”
我不想仅仅因为它的 offsetLeft 小于 0 就得出一个元素完全隐藏的结论:如果它只是小于 0 的一小部分像素并且它的右侧部分是可见的怎么办? (我同意这似乎是一个愚蠢的设计,但这些天你永远不会知道网页设计师。)最好将宽度添加到 offsetLeft 并查看结果是否仍然小于 0。以防万一。
L
Lee Taylor

接受的答案对我不起作用。

2020年细分。

(elem.offsetParent !== null) 方法在 Firefox 中运行良好,但在 Chrome 中却不行。在 Chrome 的 position:fixed 中,即使元素在页面中可见,也会使 offsetParent 返回 null。用户 Phrogz 对具有不同属性的元素进行了大型测试(2,304 个 div)来证明该问题。 https://stackoverflow.com/a/11639664/4481831。使用多个浏览器运行它以查看差异。 Demo: //Chrome 和 Firefox 结果不同 console.log(document.querySelector('#hidden1').offsetParent); //null Chrome & Firefox console.log(document.querySelector('#fixed1').offsetParent); //在 Chrome 中为 null,在 Firefox 中不为 null

(getComputedStyle(elem).display !== 'none') 不起作用,因为元素可能是不可见的,因为父显示属性之一设置为 none,getComputedStyle 不会捕捉到这一点。演示: var child1 = document.querySelector('#child1'); console.log(getComputedStyle(child1).display); //child 将显示“block”而不是“none”
U
Unmitigated

结合上面的几个答案:

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 后面,或者它的内容可能不可见但边框仍然可见。在某种程度上,“可见”是一个主观术语。


不错,但是 style.opacity、style.height 和 style.width 返回一个字符串,所以它不能与 !== 一起使用
通过样式隐藏元素的另一种方式是它的颜色可以匹配背景颜色,或者它的 z-index 可能低于其他元素。
display:none 添加到此会很棒。一个合适的工作解决方案!
M
Mac Ignacio

2021解决方案

根据MDN docs,交互观察者异步观察目标元素与祖先元素或顶级文档视口的交集的变化。这意味着每次元素与视口相交时,交互观察者都会触发。

截至2021年,目前所有浏览器都支持除IE外的交叉点观察器。

执行

const el = document.getElementById("your-target-element");
const observer = new IntersectionObserver((entries) => {
    if(entries[0].isIntersecting){
         // el is visible
    } else {
         // el is not visible
    }
});

observer.observe(el); // Asynchronous call

重要提示:IntersectionObserver 回调是异步的 =>调用 observer.observe(el) 后不会立即得到结果;
这是否仅在可见性发生变化时触发?
IE,最初创建时会触发吗?
C
Community

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

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.*/
    if (!el.offsetParent && el.offsetWidth === 0 && el.offsetHeight === 0) {
        return false;
    }
    return true;
}

旁注:严格来说,“可见性”需要先定义。就我而言,我正在考虑一个可见的元素,只要我可以在其上运行所有 DOM 方法/属性而不会出现问题(即使不透明度为 0 或 CSS 可见性属性为“隐藏”等)。


V
Vlada

如果元素是常规可见的(显示:块和可见性:可见),但某些父容器是隐藏的,那么我们可以使用 clientWidth 和 clientHeight 进行检查。

function isVisible (ele) {
  return  ele.clientWidth !== 0 &&
    ele.clientHeight !== 0 &&
    (ele.style.opacity !== '' ? parseFloat(ele.style.opacity) > 0 : true);
}

Plunker (click here)


ele.style.visibility !== 'hidden' 在这里是多余的。在这种情况下,clientWidth 和 clientHeight 将为 0。
不透明度检查需要强制编号,因为 style 值都是字符串。例如,parseFloat(ele.style.opacity) < 0.1
T
Tokimon

所以我发现是最可行的方法:

function visible(elm) {
  if(!elm.offsetHeight && !elm.offsetWidth) { return false; }
  if(getComputedStyle(elm).visibility === 'hidden') { return false; }
  return true;
}

这是基于以下事实:

display: none 元素(甚至是嵌套元素)没有宽度和高度。

即使对于嵌套元素,可见性也是隐藏的。

因此无需测试 offsetParent 或在 DOM 树中循环来测试哪个父节点具有 visibility: hidden。这即使在 IE 9 中也应该有效。

您可能会争论 opacity: 0 和折叠的元素(有宽度但没有高度 - 反之亦然)是否也不是真正可见的。但话又说回来,他们并不是每个人都说隐藏的。


G
Guy Messika

ohad navon 的回答有一点补充。

如果元素的中心属于另一个元素,我们将找不到它。

所以要确保元素的一个点被发现是可见的

function isElementVisible(elem) {
    if (!(elem instanceof Element)) throw Error('DomUtil: elem is not an element.');
    const style = getComputedStyle(elem);
    if (style.display === 'none') return false;
    if (style.visibility !== 'visible') return false;
    if (style.opacity === 0) return false;
    if (elem.offsetWidth + elem.offsetHeight + elem.getBoundingClientRect().height +
        elem.getBoundingClientRect().width === 0) {
        return false;
    }
    var elementPoints = {
        'center': {
            x: elem.getBoundingClientRect().left + elem.offsetWidth / 2,
            y: elem.getBoundingClientRect().top + elem.offsetHeight / 2
        },
        'top-left': {
            x: elem.getBoundingClientRect().left,
            y: elem.getBoundingClientRect().top
        },
        'top-right': {
            x: elem.getBoundingClientRect().right,
            y: elem.getBoundingClientRect().top
        },
        'bottom-left': {
            x: elem.getBoundingClientRect().left,
            y: elem.getBoundingClientRect().bottom
        },
        'bottom-right': {
            x: elem.getBoundingClientRect().right,
            y: elem.getBoundingClientRect().bottom
        }
    }

    for(index in elementPoints) {
        var point = elementPoints[index];
        if (point.x < 0) return false;
        if (point.x > (document.documentElement.clientWidth || window.innerWidth)) return false;
        if (point.y < 0) return false;
        if (point.y > (document.documentElement.clientHeight || window.innerHeight)) return false;
        let pointContainer = document.elementFromPoint(point.x, point.y);
        if (pointContainer !== null) {
            do {
                if (pointContainer === elem) return true;
            } while (pointContainer = pointContainer.parentNode);
        }
    }
    return false;
}

C
Community

如果我们只是收集检测可见性的基本方法,请不要忘记:

opacity > 0.01; // probably more like .1 to actually be visible, but YMMV

至于如何获取属性:

element.getAttribute(attributename);

因此,在您的示例中:

document.getElementById('snDealsPanel').getAttribute('visibility');

但是什么?它在这里不起作用。仔细观察,您会发现更新可见性不是作为元素的属性,而是使用 style 属性。这是尝试做你正在做的事情的许多问题之一。其中包括:你不能保证在一个元素中确实可以看到某些东西,仅仅因为它的可见性、显示和不透明度都有正确的值。它仍然可能缺少内容,或者可能缺少高度和宽度。另一个物体可能会掩盖它。有关更多详细信息,快速 Google 搜索会显示 this,甚至包含一个库以尝试解决问题。 (YMMV)

查看以下内容,这些可能是该问题的重复项,并提供了出色的答案,包括来自强大的 John Resig 的一些见解。但是,您的特定用例与标准用例略有不同,因此我将避免标记:

如何判断 DOM 元素在当前视口中是否可见?

如何使用javascript检查元素是否真的可见?

(编辑:OP 说他正在抓取页面,而不是创建它们,所以下面不适用)更好的选择?将元素的可见性绑定到模型属性,并始终使可见性取决于该模型,就像 Angular 对 ng-show 所做的那样。你可以使用任何你想要的工具来做到这一点:Angular、纯 JS 等等。更好的是,您可以随时间更改 DOM 实现,但您将始终能够从模型而不是 DOM 中读取状态。从 DOM 中读取你的真相是不好的。而且慢。检查模型要好得多,并信任您的实现以确保 DOM 状态反映模型。 (并使用自动化测试来确认该假设。)


我正在解析网站,这不适用于我自己的网站... :)
B
BorisOkunskiy

仅供参考,应注意 getBoundingClientRect() 在某些情况下可以工作。

例如,使用 display: none 对元素是否隐藏的简单检查可能如下所示:

var box = element.getBoundingClientRect();
var visible = box.width && box.height;

这也很方便,因为它还涵盖了零宽度、零高度和 position: fixed 的情况。但是,它不应报告用 opacity: 0visibility: hidden 隐藏的元素(但 offsetParent 也不会)。


对我来说最好的答案......简单有效。 3年后没有一个赞成票!继续展示“大众智慧”的价值。我的版本:var isVisible = el => (r => r.width && r.height)(el.getBoundingClientRect());。然后我可以通过以下方式过滤元素数组:$$(sel).filter(isVisible)
我发现它是最简单的解决方案developer.mozilla.org/en-US/docs/Web/API/Element/…
这在用户可见时不起作用....如果您滚动离开,它将保持真实
@RayFoss,您确实了解“可见”有多种定义,对吗? :) 只是为了说清楚“在 DOM 中可见”或“在屏幕上可见”或“在视口中可见”或“在带有滚动条的容器内可见”——所有这些都意味着不同的事物和实现。此外,元素的可见性如何?它是否仅在其所有像素都被渲染时才可见? (变换呢?)或者,如果只有它的“概念透明”填充当前在屏幕上,它是否可见?总而言之,我认为定义很大程度上取决于您的具体用例。
I
Israel

改进@Guy Messika 的 answer above,如果中心点 X 为 < 则中断并返回 false 0 是错误的,因为右侧的元素可能会进入视图。这是一个修复:

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

S
Scott Izu

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


L
LeeNeverGup

为了详细说明每个人的出色答案,这里是 Mozilla Fathom 项目中使用的 the implementation

/**
 * Yield an element and each of its ancestors.
 */
export function *ancestors(element) {
    yield element;
    let parent;
    while ((parent = element.parentNode) !== null && parent.nodeType === parent.ELEMENT_NODE) {
        yield parent;
        element = parent;
    }
}

/**
 * Return whether an element is practically visible, considering things like 0
 * size or opacity, ``visibility: hidden`` and ``overflow: hidden``.
 *
 * Merely being scrolled off the page in either horizontally or vertically
 * doesn't count as invisible; the result of this function is meant to be
 * independent of viewport size.
 *
 * @throws {Error} The element (or perhaps one of its ancestors) is not in a
 *     window, so we can't find the `getComputedStyle()` routine to call. That
 *     routine is the source of most of the information we use, so you should
 *     pick a different strategy for non-window contexts.
 */
export function isVisible(fnodeOrElement) {
    // This could be 5x more efficient if https://github.com/w3c/csswg-drafts/issues/4122 happens.
    const element = toDomElement(fnodeOrElement);
    const elementWindow = windowForElement(element);
    const elementRect = element.getBoundingClientRect();
    const elementStyle = elementWindow.getComputedStyle(element);
    // Alternative to reading ``display: none`` due to Bug 1381071.
    if (elementRect.width === 0 && elementRect.height === 0 && elementStyle.overflow !== 'hidden') {
        return false;
    }
    if (elementStyle.visibility === 'hidden') {
        return false;
    }
    // Check if the element is irrevocably off-screen:
    if (elementRect.x + elementRect.width < 0 ||
        elementRect.y + elementRect.height < 0
    ) {
        return false;
    }
    for (const ancestor of ancestors(element)) {
        const isElement = ancestor === element;
        const style = isElement ? elementStyle : elementWindow.getComputedStyle(ancestor);
        if (style.opacity === '0') {
            return false;
        }
        if (style.display === 'contents') {
            // ``display: contents`` elements have no box themselves, but children are
            // still rendered.
            continue;
        }
        const rect = isElement ? elementRect : ancestor.getBoundingClientRect();
        if ((rect.width === 0 || rect.height === 0) && elementStyle.overflow === 'hidden') {
            // Zero-sized ancestors don’t make descendants hidden unless the descendant
            // has ``overflow: hidden``.
            return false;
        }
    }
    return true;
}

它检查每个父母的不透明度、显示和矩形。


k
ketzer
let element = document.getElementById('element');
let rect = element.getBoundingClientRect();

if(rect.top == 0 && 
  rect.bottom == 0 && 
  rect.left == 0 && 
  rect.right == 0 && 
  rect.width == 0 && 
  rect.height == 0 && 
  rect.x == 0 && 
  rect.y == 0)
{
  alert('hidden');
}
else
{
  alert('visible');
}

请不要发布仅代码的答案。对于未来的读者来说,看到解释为什么这回答了这个问题会更有趣。此外,当您回答一个已经很好回答的旧问题时,您需要进行更多解释。
A
A.Mizrahi

const isVisible = (selector) => { let selectedElement let topElement let selectedData selectedElement = document.querySelector(selector) if (!selectedElement) { return false } selectedData = selectedElement.getBoundingClientRect() if (!selectedData || !Object.keys( selectedData)) { return false } if (!(selectedData.width > 0) || !(selectedData.height > 0)) { return false } topElement = document.elementFromPoint(selectedData.top, selectedData.left) if (selectedElement ! == topElement) { return false } return true } const output = document.querySelector('.text') output.innerHTML = '.x 元素可见:' + isVisible('.x') .block { width: 100px;高度:100px;背景:黑色; } .y { 背景:红色;边距顶部:-100px; }


如果元素被另一个重叠元素部分遮挡(在其左上角),这可能不起作用
M
Mahozad

Chrome 103 引入了 Element.isVisible(),如果元素可见则返回 true,否则返回 false

它检查会使元素不可见的各种因素,包括 display:nonevisibilitycontent-visibilityopacity


它在稳定版中可用,但目前仅在功能标志后面可用(2022 年 7 月 13 日)。
n
not_specified

这是我编写的代码,用于查找几个相似元素中唯一可见的元素,并在没有 jQuery 的情况下返回其“类”属性的值:

  // Build a NodeList:
  var nl = document.querySelectorAll('.myCssSelector');

  // convert it to array:
  var myArray = [];for(var i = nl.length; i--; myArray.unshift(nl[i]));

  // now find the visible (= with offsetWidth more than 0) item:
  for (i =0; i < myArray.length; i++){
    var curEl = myArray[i];
    if (curEl.offsetWidth !== 0){
      return curEl.getAttribute("class");
    }
  }

S
Stuart Rucker

如果您正在抓取网站,一种对我有用的非常低效的方法是突出显示任何元素,并截屏,然后检查屏幕截图是否已更改。

//Screenshot

function makeSelected(element){
    let range = new Range()
    range.selectNode(element)
    let selection = window.getSelection()
    selection.removeAllRanges()
    selection.addRange(range)
}
// screenshot again and check for diff

W
William Green

这是一种为所有 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 属性,并且用途广泛且可靠。


[element.style.display == "none"] 为我工作
A
Ajas Jansher

这就是我所做的:

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>

H
Hüseyin Çakanlı
var visible = document.getElementById("yourelementID's");
 if (visible){
          // make events
 } else
 {
   //other events
 }

这不会检查元素是否可见。它检查它是否在 DOM 中。它可能在 DOM 中并且隐藏、不显示、被另一个元素覆盖或位于视口之外。
D
DMur

在很多情况下这不一定有效,但在我的情况下,我正在使用它,它可以很好地满足我的需要。因此,如果您正在寻找一个基本解决方案(它不涵盖所有可能的情况),如果这个简单的解决方案适合您的特定需求,它“可能”对您有所帮助。

var element= document.getElementById('elementId');

if (element.style.display == "block"){

<!-- element is visible -->

} else {

<!-- element is hidden-->

}

在很多情况下,这显然是行不通的,因为 display: block 不是元素可以拥有并且仍然可见的唯一样式。