有什么方法,我可以检查如果一个元素是可见的纯JS(没有jQuery) ?
因此,给定一个DOM元素,我如何检查它是否可见?我试着:
window.getComputedStyle(my_element)['display']);
但这似乎并不奏效。我想知道我应该检查哪些属性。我想到了:
display !== 'none'
visibility !== 'hidden'
还有我可能漏掉的吗?
有什么方法,我可以检查如果一个元素是可见的纯JS(没有jQuery) ?
因此,给定一个DOM元素,我如何检查它是否可见?我试着:
window.getComputedStyle(my_element)['display']);
但这似乎并不奏效。我想知道我应该检查哪些属性。我想到了:
display !== 'none'
visibility !== 'hidden'
还有我可能漏掉的吗?
当前回答
为了详细说明大家的精彩回答,下面是Mozilla Fathom项目中使用的实现:
/**
* 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;
}
它检查每个父元素的不透明度、显示和矩形。
其他回答
根据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可能更简单一点,因为它考虑了更多的边缘情况,但我打赌它也会慢很多,所以如果你不得不多次重复这个操作,最好避免它。
来自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的元素
如果元素是常规可见的(display:block和visibility:visible),但有些父容器是隐藏的,那么我们可以使用clientWidth和clienttheight来检查。
function isVisible (ele) {
return ele.clientWidth !== 0 &&
ele.clientHeight !== 0 &&
(ele.style.opacity !== '' ? parseFloat(ele.style.opacity) > 0 : true);
}
活塞(点击这里)
公认的答案对我不起作用。
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://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