CSS :not() 选择器是否应该与遥远的后代一起使用

Is the CSS :not() selector supposed to work with distant descendants?(CSS :not() 选择器是否应该与遥远的后代一起使用?)

本文介绍了CSS :not() 选择器是否应该与遥远的后代一起使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里是 CSS3 :not() 伪类的官方文档:
http://www.w3.org/TR/css3-selectors/#negation
以及提议的 CSS 选择器 4 级增强功能:
http://dev.w3.org/csswg/selectors4/#negation p>

我一直在搜索 :not() 的实现和浏览器支持,但我发现的唯一示例是单个元素或元素的直接子元素,例如:

div *:not(p) { color: red;}

上面的例子在 <p><div> 的直接子级时有效,但在 <p><div> 的一个更远的后代.

div :not(p) {红色;}

<div><ul><li>这是红色的</li></ul><p>这不是</p><blockquote><p>这是红色的,但不应该是红色的!</p></blockquote></div>

如果答案在上面的官方文档中,那么我没有找到/理解它.正如我所说,我已经搜索了这个网站和网络,但找不到任何关于 :not() 作为另一个元素的孙子的支持或缺乏的讨论.

这应该像我认为的那样工作吗?

解决方案

这应该像我认为的那样工作吗?

不,您看到的行为是正确的.

在你的最后一个例子中,虽然 <blockquote> 包含一个 <p>,它是 <blockquote> 本身匹配 *:not(p),以及它必须是 <div> 的后代的条件,它就是.该样式仅应用于 <blockquote>,但随后由其中的 <p> 继承.

<p> 元素本身仍然计入否定,因此 <p> 本身仍然被排除在您的选择器之外.它只是从其父元素 <blockquote> 元素继承文本颜色.

即使它的相对接近的祖先都不匹配选择器,您也需要担心 htmlbody 之类的元素 - 尽管您可能只需要添加一个body 一开始的选择器:

body div...

这就是为什么我经常强烈建议不要使用 :not() 选择器来过滤后代,尤其是在没有使用类型选择器限定的情况下(例如您的示例中的 div).它并没有像大多数人期望的那样工作,并且使用像 color 这样的继承属性只会使问题更加复杂,而且会使问题变得更加更多混乱对于作者.有关更多示例,请参阅我对这些其他问题的回答:

  • 为什么这个 CSS :not() 声明没有过滤掉?
  • CSS 否定伪类 :not() 用于父级/祖先元素

所描述的问题的解决方案是简单地将不同的颜色应用于 <p> 元素.由于继承,您将无法使用选择器简单地排除它们:

/* 应用于 div 并让其所有后代继承 */分区 {红色;}/* 从 div p 中删除它 */分区 p {颜色:黑色;}

在选择器级别 4:是的,:not() 确实得到了增强,可以接受包含组合器的完整复杂选择器.本质上,这意味着(一旦浏览器开始实现它)您将能够编写以下选择器并让它完全按照您的意愿行事:

p:not(div p) {红色;}

如果有人感兴趣,这适用于今天的 jQuery.

Here is the official documentation for the CSS3 :not() pseudo-class:
http://www.w3.org/TR/css3-selectors/#negation
and the proposed CSS Selectors Level 4 enhancement:
http://dev.w3.org/csswg/selectors4/#negation

I've been searching the implementation and browser support for :not(), but the only examples I found were with a single element or with a direct child of an element, e.g.:

div *:not(p) { color: red; }

The example above works when <p> is a direct child of <div>, but it does not work when <p> is a more distant descendant of <div>.

div :not(p) {
    color: red;
}

<div>
    <ul>
        <li>This is red</li>
    </ul>
    <p>This is NOT</p>
    <blockquote><p>This is red but is not supposed to be!</p></blockquote>
</div>

If the answer is in the official documentation above, then I didn't find/understand it. As I said, I have searched this site and the web but couldn't find any discussion about the support or lack thereof of :not() as grand-children of another element.

Is this supposed to work like I think it should?

解决方案

Is this supposed to work like I think it should?

No, the behavior you're seeing is correct.

In your last example, although the <blockquote> contains a <p>, it's the <blockquote> itself that's matching *:not(p), as well as the condition that it must be a descendant of the <div>, which it is. The style is applied only to the <blockquote>, but it is then inherited by the <p> inside it.

The <p> element itself still counts against the negation, so the <p> itself is still being excluded from your selector. It's just inheriting the text color from its parent, the <blockquote> element.

Even if none of its relatively close ancestors matched the selector, you have elements like html and body to worry about as well — although you could probably just tack on a body selector in the very beginning:

body div...

This is why I often strongly advise against using the :not() selector for filtering descendants, especially when not qualified with a type selector (like div in your example). It doesn't work the way most people expect it to, and the use of inherited properties like color only serves to compound the problem, on top of making it even more confusing for authors. See my answers to these other questions for more examples:

  • Why doesn't this CSS :not() declaration filter down?
  • CSS negation pseudo-class :not() for parent/ancestor elements

The solution to the problem described is to simply apply a different color to <p> elements. You won't be able to simply exclude them with a selector because of inheritance:

/* Apply to div and let all its descendants inherit */
div {
  color: red;
}

/* Remove it from div p */
div p {
  color: black;
}

On Selectors Level 4: yes, :not() has indeed been enhanced to accept full complex selectors that contain combinators. Essentially, this means (once browsers begin implementing it) you will be able to write the following selector and have it do exactly what you want:

p:not(div p) {
  color: red;
}

In case anyone is interested, this works in jQuery today.

这篇关于CSS :not() 选择器是否应该与遥远的后代一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:CSS :not() 选择器是否应该与遥远的后代一起使用

基础教程推荐