1

I am trying to target a paragraph only if it is not inside the custom component my-component. like this:

// Style all elements that are NOT inside my-component
:not(my-component) *{
    color: red;
}

With the answer from @Frox we can see that we can target everything except the my-component container

body :not(my-component *) {
   color: red
}

But if we specify one more level to target every p except the p inside my-component it's still selecting the p...

body :not(my-component *) p{
   color: red
} 

Can anyone explain why this isn't working or if it's a bug or if it's just not possible?

/* Style all elements that are descendants of body and NOT inside my-component */
body :not(my-component *) p{
  color: red;
}

.container {
  border: 1px solid #ccc;
  padding: 10px;
  margin-bottom: 20px;
}
<div class="container">
  <p>This paragraph is outside the special container → should be <strong style="color:red;">RED</strong>.</p>
</div>

<my-component class="container">
  <p>This paragraph is inside the special container → should be <strong >black</strong>.</p>
  <span>Another span-element inside → black</span>
</my-component>

<div class="container">
  <p>Another outside paragraph → RED</p>
  <span>another span outsize my-component</span>
</div>

My final goal is to have a style rule that exempts part of the page but targets everything else.

:not(header) {
    my-dropdown-component {}
}

3 Answers 3

1

First, to answer your question about why the selectors are doing such behaviors, there are actually 2 misconceptions:

  1. You are asking why :not is not working correctly:

    • body :not(my-component *) p doesn't mean what you are asking for (target a paragraph only if it is not inside my-component). my-component is not the child of itself (the my-component * part), so it matches :not(my-component *). As expected, paragraph element will be matched by :not(my-component *) p.

    • :not(my-component) * doesn't mean to select all child elements that is not under my-component. It selects all child elements (the * part) of all elements that are not my-component (the :not(my-componenet) part). p is a child of something (like body and html), so it is selected.

  2. Why body :not(my-component *) still makes p red: The color property is inherited by default. So if you make my-component red, without resetting the style on p, it will also inherit the red color by default even if it is not selected.

The combination of these 2 misconception explains why nothing works as you expected.

Now since you asked:

I am trying to target a paragraph only if it is not inside the custom component my-component.

I would just do p:not(my-component p):

p:not(my-component p) {
  color: red;
}

.container {
  border: 1px solid #ccc;
  padding: 10px;
  margin-bottom: 20px;
}
<div class="container">
  <p>This paragraph is outside the special container → should be <strong style="color:red;">RED</strong>.</p>
</div>

<my-component class="container">
  <p>This paragraph is inside the special container → should be <strong >black</strong>.</p>
  <span>Another span-element inside → black</span>
</my-component>

<div class="container">
  <p>Another outside paragraph → RED</p>
  <span>another span outsize my-component</span>
</div>

My final goal is to have a style rule that exempts part of the page but targets everything else.

This is too vague to answer. Note that p:not(my-component p) will also cause p's child to inherit p's color though. You can reset their style if this is not desired.

Sign up to request clarification or add additional context in comments.

Comments

1

Analyzing the existing selector:

*:not(my-component) *

* at the beginning is irrelevant.

:not(my-component) selects everything that is not my-component, which includes <html> and <body>.

The universal selector at the end selects everything descendant from <html>. Which is everything except the <html> itself.

That is not what we want.


Analyzing alternative:

body :not(my-component *)

body at the beginning to limit ourselves to descendants of <body>.

my-component * selects all children of my-component. Then we pass the above as the argument of :not() i.e. :not(my-component *) to say everything that is not a descendant of my-component.

All together we have:

All elements that are descendants of body but not descendants of my-component.


This does include my-component itself but I believe that is what you are looking for:

Style all elements that are NOT inside my-component

my-component * {
  color: green;
}

/* Style all elements that are descendants of body and NOT inside my-component */
body :not(my-component *) {
  color: red;
}

body :not(my-component *) h4 {
  color: blue;
}

.container {
  border: 1px solid #ccc;
  padding: 10px;
  margin-bottom: 20px;
}
<div class="container">
  <p>This paragraph is outside the special container → should be <strong style="color:red;">RED</strong>.</p>
  <h4>Demostration h4 → should be BLUE.</h4>
</div>

<my-component class="container">
  <p>This paragraph is inside the special container → should be <strong style="color:green;">GREEN</strong>.</p>
  <span>Another element inside → GREEN</span>
</my-component>

<div class="container">
  <p>Another outside paragraph → RED</p>
</div>

2 Comments

This is a good attempt - but if we add one further level like :not(my-component *) p it is not working.
I have edited the snippet to demonstrate that further levels work without issue.
0

All elements that are inside the body are also not inside my-component. Since the "red" rule is after the "green" rule it takes precedence. Reorder the rules to solve the problem:

/* Style all elements that are NOT inside my-component */
*:not(my-component) * {
  color: red;
}

my-component * {
  color: green;
}

.container {
  border: 1px solid #ccc;
  padding: 10px;
  margin-bottom: 20px;
}
<div class="container">
  <p>This paragraph is outside the special container → should be <strong style="color:red;">RED</strong>.</p>
</div>

<my-component class="container">
  <p>This paragraph is inside the special container → should be <strong style="color:green;">GREEN</strong>.</p>
  <span>Another element inside → GREEN</span>
</my-component>

<div class="container">
  <p>Another outside paragraph → RED</p>
</div>

3 Comments

But that's exactly the problem isn't it? I know that the other one can overwrite the style but how can i achieve the goal of not having "All elements that are inside the body are also not inside my-component"
Changing the order of the rules makes the green rule override the red rule. Run the snippet.
I know :) That is clear to me but the not() selector shouldn't even target the children of my-component on the first hand. I tried to clarify my question :)

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.