我们有一个选择器: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>
其他浏览器是否有类似的解决方案?
答案 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
:
li:empty::before { content: '(empty)'; font-style: italic; color: #999; }
&#13;
<ul>
<li>
</ul>
<ul>
<li></li>
</ul>
&#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编辑器(也不是我想要的)不是我的工作,但我可以编写一个非常简单的脚本来处理我的一些工作。这对我来说似乎是更好的答案,除了培训支持团队在编辑时管理他们的空白。