【问题标题】:Firefox, query selector and the visible pseudo selectorFirefox,查询选择器和可见的伪选择器
【发布时间】: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。

标签: javascript firefox selectors-api


【解决方案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>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-02-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-19
        • 2019-01-22
        • 2012-07-20
        • 1970-01-01
        相关资源
        最近更新 更多