空选或空白的CSS选择器

时间:2015-07-13 12:03:39

标签: html css css-selectors

我们有一个选择器:empty可以在完全为空时匹配该元素:

<p></p>

但是我的条件可能是空的,或者它可能包含换行符或空格:

<p>    </p>

我找到了Firefox的解决方案,:-moz-only-whitespace

:empty { width: 300px; height: 15px; background: blue; }
:-moz-only-whitespace { width: 300px; height: 15px; background: orange; }
<p></p>
<p>    </p>
<p>This is paragraph three.</p>

其他浏览器是否有类似的解决方案?

2 个答案:

答案 0 :(得分:18)

虽然问题描述了一个<p>元素,其中包含一些常规空格字符,这似乎是一种疏忽,但更常见的是标记元素只包含缩进和空行形式的空格,如:

<ul class="items">
  <li class="item">
    <div>
      <!-- Some complex structure of elements -->
    </div>
  </li>
  <li class="item">
  </li> <!-- Empty, except for a single line break and
             indentation preceding the end tag -->
</ul>

上面示例中的某些元素(如<li>以及<p>)具有可选的结束标记,这可能会导致DOM处理中出现意外的副作用,并且存在元素间空白。例如,以下两个<ul>元素不会产生等效的节点树,特别是第一个元素不会产生li:empty

&#13;
&#13;
li:empty::before { content: '(empty)'; font-style: italic; color: #999; }
&#13;
<ul>
  <li>
</ul>
<ul>
  <li></li>
</ul>
&#13;
&#13;
&#13;

鉴于HTML considers inter-element whitespace to be transparent by design,想要使用CSS来定位这些元素并不是不合理的,而不必诉诸于修改HTML或生成它的应用程序(特别是如果你最终必须实现和测试这是一个特殊情况。)

如上所述,:blank pseudo-class in Selectors 4将解决此问题。不幸的是,它没有达到目前的标准,要么是因为它没有提前提出,要么就是没有机会充实它。即使它的名字还没有最终确定,并且不清楚所描述的行为是否已经过测试或最终确定。

由于这是一项相对较新的标准提案,因此在:-moz-only-whitespace之外没有已知的实施方案,MDN有this说:

  

:-moz-only-whitespace伪类匹配根本没有子节点的元素,或者空文本节点或仅包含空格的文本节点。只有当元素中有元素节点或文本节点包含一个或多个字符时,该元素才会再与该伪类匹配。

......经过仔细检查,确实看起来与规范对:blank的描述一致,但由于它是非标准的,尚未最终确定,我建议不要使用它在生产中。

由于它未在其他任何地方实施,因此目前在任何其他浏览器中都没有相应的内容。与此同时,修改HTML 唯一的选择,无论是在源头,还是通过使用脚本的DOM操作。

答案 1 :(得分:3)

@BoltClock为这个问题提供了一个很棒的答案,表明只有CSS才能实现(目前,使用CSS规范3)。

@BoltClock提到可以使用伪选择器:empty来定位真正为空的元素(这是一个如所解释的奇怪定义)。此伪选择器仅在CSS 3中可用,并且不会选择仅包含空格作为内容的元素。

@BoltClock表示清理只有空格作为内容的元素的唯一方法是修复HTML,但这并不完全正确。这也可以通过实现Javascript来实现。

保持谨慎!我提供的解决此问题的Javascript可能需要很长时间才能执行,因此最好的方法是尽可能清理原始HTML。如果那是不可能的,那么这可以作为解决方案,只要你没有太多的DOM树。

我将介绍如何自己编写脚本的步骤......

首先,在页面加载后启动所有内容。

这应该是非常明显的。在运行脚本之前,您需要确保DOM已完全加载。为页面加载添加event listener

window.addEventListener("load", cleanUpMyDOM);

...当然,在此之前,请创建名为function的{​​{1}}。我们将在此函数中编写其余的逻辑。

第二次,收集我们正在检查的元素。

在我们的示例中,我们将检查整个DOM,但这是我们的脚本非常广泛的地方,可能会使您的页面无响应。您可能希望限制迭代的节点数量。

我们可以使用cleanUpMyDOM抓取相关节点。这个函数的优点在于它将平衡DOM树,我们不必递归每个节点的子节点。

document.querySelectorAll

正如我之前所说,此代码将抓取每个DOM节点,这可能不是一个好主意。

例如,我正在使用WordPress,并且一些内部页面中有一些垃圾。幸运的是,它们都是var nodes = document.querySelectorAll("*"); 元素的p元素,因此我可以将我的选择器更改为div.body,这将只选择document.querySelectorAll("div.body p")元素作为子元素我的p元素递归。这将极大地优化我的脚本。

第三次,迭代节点并找到空的节点。

我们将为div.body数组创建一个循环并检查其中的每个节点。然后我们必须检查节点是否为空。如果它为空,我们将为其应用一个名为nodes的类。

我只是在这里拍摄,所以如果你发现这段代码有误,请告诉我。

blank

我确信上面有一个更简洁的方法来编写循环,但这应该可以完成工作。

最后,您需要做的就是使用CSS定位空白元素。

将此规则添加到样式表中:

for(var i = 0; i < nodes.length; i++){
    nodes[i].innerHTML = nodes[i].innerHTML.trim();
    if(!nodes[i].innerHTML)
        nodes[i].className += " blank";
}

你有它!您的所有“空白”节点都已隐藏。

对于那些只想继续前进的人来说,这是完成的脚本:

.blank {
    display:none;
}

如果您发现我的代码有任何问题,请再次告知我们。

希望这有帮助!

P.S。许多人可能想知道你为什么要这样做,因为它确实感觉不好。我会避免这样做,但我处于一种我开始考虑它的情况。我网站上的页面内容是通过WYSIWYG编辑器创建的。这个内容是由营销团队不断创建和修改的,我很不知所措,为他们的漏洞提供支持。修复WordPress的WYSIWYG编辑器(也不是我想要的)不是我的工作,但我可以编写一个非常简单的脚本来处理我的一些工作。这对我来说似乎是更好的答案,除了培训支持团队在编辑时管理他们的空白。