【问题标题】:Cascading with CSS :not pseudo-class与 CSS 级联:不是伪类
【发布时间】:2016-05-05 05:58:50
【问题描述】:

我很困惑为什么这个例子不起作用:

CSS:

p {
  color: red;
}

div:not(.exclude) p {
  color: green;
}

HTML:

<div>
  <div class="exclude">
    <p>I should be red</p>
  </div>
  <div>
    <p>I should be green</p>
  </div>
</div>

最终结果是&lt;p&gt; 都是绿色的,但我预计第一个是红色的。 Here's a JSFiddle.

有趣的是,我发现了三种不同的方法来让它工作:

  1. Remove 来自 HTML 的顶级 &lt;div&gt;
  2. Change 顶级&lt;div&gt; 到不同的元素(例如&lt;section&gt;
  3. Add 一个额外的 div 到第二个 CSS 选择器的开头 (div div:not(.exclude) p)

还有另一种奇怪的方法来打破它:

  1. 使用解决方案 2 作为基础,wrap 另一个 &lt;div&gt;&lt;section&gt; 周围

According to MDN:

这个选择器只适用于一个元素;你不能用它来排除所有的祖先。例如,body :not(table) a 仍将应用于表内的链接,因为&lt;tr&gt; 将匹配选择器的:not() 部分。

这是有道理的,但我认为这里不会发生这种情况。由于&lt;div class="exclude"&gt; 与其直接子&lt;p&gt; 之间没有任何内容,因此无论嵌套在什么内部,它都应该触发该规则。我错过了什么?如果有人能帮助我理解这一点,我将不胜感激。

【问题讨论】:

    标签: html css dom css-selectors


    【解决方案1】:

    您在使用:not 时发现了一个常见的陷阱,其他答案也对此进行了描述。 CSS 中处理这个问题的经典方法,以及我们在 CSS3 之前为我们提供:not 的能力,我们这样做的方式是编写几个规则,一个处理一般情况,第二个有这个特例。在您的情况下,这看起来像:

    p             { color: red;   }
    div p         { color: green; }
    div.exclude p { color: red;   }
    

    【讨论】:

      【解决方案2】:

      由于&lt;div class="exclude"&gt; 与其直接子&lt;p&gt; 之间没有任何内容,因此无论嵌套在什么内部,它都应该触发该规则。我错过了什么?

      &lt;p&gt; 是顶级&lt;div&gt;&lt;div class="exclude"&gt; 的后代。因此,虽然后者不匹配选择器,但前者匹配,因此您有一个匹配项。与选择器不匹配的祖先比匹配选择器的祖先更接近&lt;p&gt; 也没关系。

      解决方案 1 和 2 通过完全消除匹配来起作用。

      &lt;p&gt; 的祖先中不存在其他 &lt;div&gt;s 时,解决方案 3 有效,因为您将选择器限制为那些确切的条件,按照确切的顺序。这意味着如果您将类属性从内部 &lt;div&gt; 交换到外部,它将不再匹配选择器,反之,如果您将类 selector 从内部 div 交换到最外层,选择器与原始 HTML 结构不匹配(再次假设层次结构中不存在其他 &lt;div&gt;s)。

      &lt;section&gt; 周围包装另一个&lt;div&gt; 只会导致选择器再次与&lt;div&gt; 匹配。 &lt;section&gt; 被忽略,与&lt;div class="exclude"&gt; 的方式大致相同。

      另见:

      【讨论】:

      • 你说得对,我是从下往上考虑的,而我应该从上往下考虑。 &lt;p&gt; 在到达 &lt;div class="exclude"&gt; 之前就变成了绿色。感谢您的详尽解释!
      • @Jerome Dahdah:在我看来,&lt;div class="exclude"&gt; 从未被考虑过。有p吗文档中某处是否有 div:not(.exclude) ?如果是这样,p 是否出现在该 div 中?如果所有这些问题的答案都是肯定的,那么你就有了匹配。这样做的好处是,我可以从下往上或从上往下查看它,无论哪种方式都可以。
      • 所以你已经解释了他的解决方案是如何工作的,但是你还没有解释如何做到这一点没有改变 HTML,这不是问题的明确部分,但作为答案的一部分似乎非常有用。
      【解决方案3】:

      你的&lt;div&gt; 甚至高于&lt;div class="exclude"&gt;

      在你的风格中,你已经指出——就:not伪类而言——任何祖先&lt;div&gt;都可以。 (即祖父母&lt;div&gt; 和父母&lt;div&gt; 一样好。)

      要关注直接父级,您的 CSS 需要使用直接子级选择器 (&gt;):

      p {
      color: red;
      }
          
      div:not(.exclude) > p {
      color: green;
      }
      <div>
        <div class="exclude">
          <p>I should be red</p>
        </div>
        <div>
          <p>I should be green</p>
        </div>
      </div>

      【讨论】:

      • 是的 - 您可以使用 :not(); 过滤祖先;仅当您将其与后代组合器和/或通用选择器一起使用时,它才会成为问题。将它与子选择器一起使用是可靠的,因为您将检查限制为直接祖先(也称为父级),因此不会有太多出错的余地。
      猜你喜欢
      • 2013-08-10
      • 1970-01-01
      • 1970-01-01
      • 2017-05-27
      • 2015-07-31
      • 2012-06-29
      • 1970-01-01
      • 2011-07-14
      相关资源
      最近更新 更多