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 不是 nonevisibility 不是 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,查询选择器和可见的伪选择器的主要内容,如果未能解决你的问题,请参考以下文章

jQuery选择器和选取方法

关于伪元素选择器

jQuery选择器和选取方法

html的伪类选择器

jQuery选择器和选取方法.RP

CSS伪类选择器和伪元素选择器