Firefox,查询选择器和可见的伪选择器
Posted
技术标签:
【中文标题】Firefox,查询选择器和可见的伪选择器【英文标题】:Firefox, query selector and the visible pseudo selector 【发布时间】:2012-11-03 12:39:09 【问题描述】:是否可以使用带有 Firefox 的 querySelector() 或 querySelectorAll() 函数的伪选择器来检测可见性?特别是我希望能够做这样的事情:
elem.querySelector('#list .list-item:visible');
elem.querySelector('#section .sub-section:visible .title');
无需担心浏览器不一致或其他实现,只需 Firefox。谢谢!
编辑:可见是由 display 不是 none 和 visibility 不是 hidden。
【问题讨论】:
你对“可见性”的定义是什么? DOM 元素的 display 设置为 block 可以工作,但理想情况下它也会检查 visibility 是否设置为 visible。 【参考方案1】:由于 :visible 伪选择器没有原生实现,我决定使用 CSS 类来隐藏和显示我的元素,因此只需检查类名而不是可见性。这是我的选择器现在的样子:
elem.querySelector('#list .list-item:not(.hidden)');
现在在 2016 年我们还可以使用隐藏的 html5 属性,所以这个选择器也可以工作:
elem.querySelector('#list .list-item:not([hidden])');
【讨论】:
这还是2015年最好的方式吗? 我相信, :visible 不是而且可能永远不会成为 css 规范的一部分。 在 2016 年更流行的方法是使用新的隐藏 html5 全局属性。它不完全向后兼容,所以要小心。这是 Mozilla 的文档developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/… @SuperUberDuper hidden 属性将元素显示设置为无。所以不,它不考虑不透明度。【参考方案2】:不,没有。 The CSS specification 没有定义 :visible
(或相关的)选择器,AFAIK Firefox 没有实现非标准的伪选择器。
如果您想自己实现,请注意 jQuery 如何实现其:visible
选择器:
在 jQuery 1.3.1(和更早的版本)中,如果元素的 CSS“显示”不是“无”,它的 CSS“可见性”不是“隐藏”,并且它的类型(如果是输入)是不是“隐藏”的。 在 jQuery 1.3.2 中,如果浏览器报告的 offsetWidth 或 offsetHeight 大于 0,则元素可见。
来源:http://docs.jquery.com/Release:jQuery_1.3.2#:visible.2F:hidden_Overhauled
【讨论】:
这就是我所担心的……太糟糕了。我知道它对 CSS 来说不是一个有用的伪选择器,但它在 javascript 中真的很有帮助。 jQuery 实现在检测 css 可见性属性方面并不能很好地工作,因为visibility: hidden
将占用文档空间
在哲学层面上也许这是正确的实现...取决于您认为可见的内容...如果它在页面上占用空间,那么有一些空间可以争论该元素是“可见”。【参考方案3】:
对于查找不是display:none
的元素,等效于:visible
的CSS 选择器是
:not([style='display:none'])
如果需要,您可以对 visibility:hidden
执行相同的操作,然后链接 :not()
选择器。
这是fiddle。
编辑:注意空格和其他标点符号。如果您稍后使用 JQuery 和 hide()
操作这些元素,并且需要调用相同的函数,那么您需要将 :not([style="display: none;"])
链接到您的 CSS 选择器。
【讨论】:
【参考方案4】:使用纯 javascript,您还可以轻松模拟 jQuery 行为,将您的 querySelector 结果转换为数组,并对其进行过滤:
Array.prototype.slice.call(document.querySelectorAll('your selector'))
这将创建一个包含选择器结果的普通数组,您可以将其过滤为:
.filter(function (item,index) return item.style.display!="none" );
甚至是其他的 jquery 条件 (item.style.visibility != "hidden" && item.style.opacity > 0 && ...
)。
作为一个班轮:
Array.prototype.slice.call(document.querySelectorAll('your selector')).filter(function (item,index) return item.style.display!="none" );
【讨论】:
【参考方案5】:检查元素是否可见,支持所有主流浏览器:
jQuery:
$('.list-item').is(':visible');
原版JS:
function isVisible(elem) return elem.offsetWidth > 0 || elem.offsetHeight > 0 || elem.getClientRects().length > 0;
【讨论】:
你确定这两个例子在所有版本的 jQuery 中都是等价的吗? @macguru2000 它们在最新版本的 jQuery 中是等价的,我没有检查(因此从未提及)早期版本的 jQuery 关于这个方法。 我明白了,请不要误会,但是当您这样做十多年后,您就不再认为提及意味着“最新版本”。想想其他人在 2 年内阅读您的答案会怎么想,jQuery3?【参考方案6】:您可以使用offsetParent
值来确定元素是否可见。
let parent = document.getElementById('parent');
let allSubChildren = parent.querySelectorAll('.sub-children');
let visibleChildren = Array.prototype.slice.call(allSubChildren).filter(function (item, index)
console.log('Element "' + item.textContent + '" is ' + (item.offsetParent !== null ? 'visible' : 'hidden'));
return item.offsetParent !== null;
);
console.log(visibleChildren);
.none
display: none;
.hidden
visibility: hidden;
<p><b>item.offsetParent</b> returns <b>null</b> if the element or any parent is not displayed.</p>
<em>Check the console</em>
<div id="parent">
<div class="children">
<div class="sub-children">visible</div>
</div>
<div class="children hidden">
<div class="sub-children">visibility hidden doesn't work</div>
</div>
<div class="children none">
<div class="sub-children">display none</div>
</div>
<div class="children">
<div class="sub-children">also visible</div>
</div>
<div class="children">
<div class="sub-children none">also display none</div>
</div>
</div>
<div id="result">
</div>
【讨论】:
以上是关于Firefox,查询选择器和可见的伪选择器的主要内容,如果未能解决你的问题,请参考以下文章