2

I am trying to figure out how :not selector works. First of all I try this code

<!DOCTYPE html>
<html>
<head>
<style>

p {
    color: #000000;
}

:not(p) {
    color: #ff0000;
}
</style>
</head>
<body>

<h1>This is a heading</h1>

<p class="example">This is a paragraph.</p>
<p>This is another paragraph.</p>

<div>This is some text in a div element.</div>

</body>
</html>

It works as ı expect the paragraphs aren't styled and the text in the div and the heading are red. After that I am changing the part in the style tags to this:

<style>
    :not(p) {
        color: #ff0000;
    }
</style>

This time it doesn't work as I expected. Although I want all the elements that are not paragraphs to be red all of them are displayed as red.

Furthermore I am changing the code between the style tags to this:

<style>
:not(p.example) {
    color: #ff0000;
}
</style>

This time I am expecting the elements doesn't fit to "p.example" (h1, div and the second paragraph) to be red but none of the elements are affected.

What do I miss? Shouldn't the examples shown above select all the elements those don't fit to the argument selector? Is there a rule about not using the :not selector alone (e.g not as p:not or h1:not)?

4 Answers 4

3

Neither of the previous answers is entirely correct.

In your second case, merely specifying

:not(p)

colors everything red because it colors the body, and color is inherited.

You to NOT have to specify, as one answer claims,

body :not(p) {
    color: #ff0000;
}

That is almost exactly equivalent to :not(p) (which means *:not(p)). Nor do you have to specify any other parent such as .main as another answer claims.

The third example fails because the argument to :not is not a simple selector. The syntax you gave seems to be trying to do is to select everything that is not a p with the example class. As another respondent pointed out, what you probably meant was everything that is a p but without the example class, for which p:not(.example) is correct.

To select elements which are not A and not B (in other words not (A or B), just do

:not(A):not(B)

For example,

:not(h1):not(p)

which in this example will apply to the body and the div. A more realistic example would be to select p's other than those with either of two classes:

p:not(.class1):not(.class2)
Sign up to request clarification or add additional context in comments.

1 Comment

This. It is about inherited properties. The op isn't doing anything wrong in the first part of the problem. stackoverflow.com/questions/27188313/…
3

The selector :not(p) matches all elements except p elements. This includes the body element. When your only style sheet is :not(p) { color: #ff0000; }, you thus set all content color red, since the p elements inherit color from their parents (here p) when no color is set on them directly.

If you want to set the color of content to red except for p elements and their descendants, you thus need to be more explicit. A simple way, assuming that this all you want to color, is to set the overall color to red and then override it for p elements, letting inner elements inherit color:

body { color: red }
p { color: black }

The reason why :not(p.example) does not work at all is that the operand of :not must be a simple selector, namely a type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class, but not any combination of these; and p.example isn’t simple.

You could use the combined selector :not(p):not(.example), which matches any element except p elements in class example. And this is probably what you want. But the rule won’t work the way want, since here, too, the selector matches the body element, among other things, and its color gets inherited by the only element that has not got color specified for it directly. So even in this case, you would need to think otherwise, setting e.g.

body { color: red }
p.example { color: black }

1 Comment

Thanks for your answer. It seems it also corrected the :not(p):not(.example) part of the other answer. But both of your answers clearly answered my question and I accepted the other one as accepted because it made me notice earlier what I am doing wrong. As I am not able to accept two answers I am going to upvote your answer.
3

After @abhitalks comments/feedback. In your first example is nothing wrong, just is related to only inherited properties which will not work. color is inherited, but border is not:

Take a look here Full property table

:not(p) {
  color: #f00;
  border: 1px solid gray;
}
<h1>This is a heading</h1>

<p class="example">This is a paragraph.</p>
<p>This is another paragraph.</p>

<div>This is some text in a div element.</div>

In you second example:

Selectors level 3 does not allow anything more than a single simple selector within a :not() pseudo-class.

You can change it to:

body :not(.example) {
  color: #ff0000;
}
<h1>This is a heading</h1>

<p class="example">This is a paragraph.</p>
<p>This is another paragraph.</p>
<div>This is some text in a div element.</div>

9 Comments

In your first example the syntax in incorrect...So you have to define E(e.g. body)... -- Not necessarily. :not(x) notation is perfectly fine. It means *:not(x). But, the confusion is that why it works only when a previous style is present (on E or X). See this fiddle: jsfiddle.net/abhitalks/m4n07Lt1 . If you remove the first class, then it stops working. You add any class before it (targetting E or X) and it will work. Does CSS spec say something about implied context?
And yes, body :not(p) is not equivalent to E:not(x) because it is not body:not(p). Notice the space. It becomes a descendant as in body *:not(p). So, this must be something to do with descendant/context
Hmm probably you are right @abhitalks. Still wonder why i can't reproduce to jsfiddle. Is probably something with html structure or whatever
And I also noticed that the previous style should target the same properties. If the previous class styles color, then :not(p) { font-weight: bold; won't work.
Who downvoted this answer, without understanding what's going on? This answer is very much useful. Not fair.
|
-1

When you use :not selector, you should mentioned some parent. Based on that parent only it will work. Otherwise it will select all the elements only.

 <div class="main">

  <h1>This is a heading</h1>
  <p class="example">This is a paragraph.</p>
  <p>This is another paragraph.</p>

  <div>This is some text in a div element.</div>
</div>

CSS:

 .main :not(p) {
   color: #ff0000;
 }

Also if you don't want to select particular element using :not selector you need to use like below.

 p:not(.example)
{
  color:green;
}

FIDDLE DEMO

1 Comment

you should mentioned some parent -- this is wrong. See the specs linked to by Alex in the other answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.