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

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

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

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

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

还有我可能漏掉的吗?


当前回答

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

例如,使用display: none简单检查元素是否被隐藏,可能看起来像这样:

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

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

其他回答

2021的解决方案

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

截至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

The handler will fire when initially created. And then it will fire every time that it becomes slightly visible or becomes completely not visible. An element is deemed to be not-visible when it's not actually visible within the viewport. So if you scroll down and element goes off the screen, then the observer will trigger and the // el is not visible code will be triggered - even though the element is still "displayed" (i.e. doesn't have display:none or visibility:hidden). What matters is whether there are any pixels of the element that are actually visible within the viewport.

结合上面的几个答案:

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

根据MDN文档,元素的offsetParent属性将在它或它的任何父元素通过display style属性被隐藏时返回null。只要确保元素不是固定的。一个脚本来检查这个,如果你没有位置: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可能更简单一点,因为它考虑了更多的边缘情况,但我打赌它也会慢很多,所以如果你不得不多次重复这个操作,最好避免它。

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()规范草案。

我有一个更有效的解决方案相比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可见性属性是“隐藏”等)。