与CSS级联:不是伪类

时间:2016-01-28 02:09:39

标签: html css css3 dom css-selectors

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

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>

最终结果是<p>都是绿色的,但我原本预计第一个是红色的。 Here's a JSFiddle.

有趣的是,我找到了三种不同的方法来实现它:

  1. Remove来自HTML
  2. 的顶级<div>
  3. Change顶级<div>到另一个元素(例如<section>
  4. Add额外div到第二个CSS选择器的开头div div:not(.exclude) p
  5. 另一个奇怪的方法来打破它:

    1. 使用解决方案2作为基础,在<div>
    2. 周围wrap另一个<section>

      According to MDN

        

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

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

3 个答案:

答案 0 :(得分:6)

  

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

<p>是顶级<div><div class="exclude">的后代。因此,虽然后者与选择器不匹配,但前者确实如此,因此您有匹配。无法匹配选择器的祖先比那个选择器更接近<p>并不重要。

解决方案1和2完全消除了这一匹配。

解决方案3在<div>的祖先中不存在其他<p>时有效,因为您将选择器限制为那些确切的条件,按照确切的顺序。这意味着如果您将class属性从内部<div>交换到外部属性,它将不再与选择器匹配,相反,如果您从内部{{1>交换了类选择器对于外部的选择器,选择器将与原始HTML结构不匹配(同样,假设层次结构中不存在其他div。)

<div>周围包裹另一个<div>会导致选择器再次与<section>匹配。忽略<div>,与<section>的方式大致相同。

另见:

答案 1 :(得分:4)

您的覆盖率<div>甚至高于<div class="exclude">

在你的风格中,你已经指出 - 就:not伪类而言 - 任何祖先<div>都会这样做。 (即祖父母<div>和父母<div>一样好。)

要专注于直接父级,您的CSS需要使用直接子选择器(>):

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>

答案 2 :(得分:1)

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

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