3

I have a very simple selector that works, but when adding it to a :not() it no longer seems to recognize it.

h2:not([random-attribute~="value"] h2){
  color: red;
}
[random-attribute~="value"] h2{
  color: blue;
}
<div class="content">
  <h2>Same valid selector, not working</h2>
  <div random-attribute="value">
      <h2>Valid selector turned blue.</h2>
  </div>
</div>

From what I understand, if you put a valid selector inside the not() you will get any h2 element that is not whatever is inside the parenthesis. This is intuitive.

What isn't intuitive, is that the selector within the not() is valid and works when used alone, but when added to the not() it doesn't seem to work.

Is this not a valid way to write this?

Paulie_D
  • 95,305
  • 9
  • 106
  • 134
leigero
  • 3,127
  • 10
  • 39
  • 60
  • 1
    No..because there is no parent selector. – Paulie_D Oct 18 '16 at 18:16
  • No, the `:not` in your case means _a h2 that does not have an attribute called random-attribute..._ – Ason Oct 18 '16 at 18:22
  • There is no parent selector in CSS. You can't start with the `h2` then traverse up to the `
    `, even when using `not()`. That selector may work on its own but does not do what you want when prefixed with `h2`. It will actually look for an `h2` that is does not have that attribute: http://stackoverflow.com/questions/1014861/is-there-a-css-parent-selector
    – skyline3000 Oct 18 '16 at 18:22

4 Answers4

6

You need to style all h2 element that are descendants of elements that are not [random-attribute~="value"] then style h2 that are.

It doesn't hurt to qualify the selector with a direct child combinator too.

Like so:

*:not([random-attribute~="value"]) > h2 {
  color: red;
}
[random-attribute~="value"] > h2 {
  color: blue;
}
<div class="content">
  <h2>Same valid selector, not working</h2>
  <div random-attribute="value">
    <h2>Valid selector turned blue.</h2>
  </div>
</div>

<h2>some other heading</h2>
Paulie_D
  • 95,305
  • 9
  • 106
  • 134
  • Note `:not([random-attribute~="value"]) > h2` matches `h2` whose parent does not match `[random-attribute~="value"]`. Not `h2` whose ancestors don't match `[random-attribute~="value"]` – Oriol Oct 18 '16 at 19:28
2

You have the syntax wrong for ([random-attribute~="value"] h2) It should just be ([random-attribute~="value"]). See below:

h2:not([random-attribute~="value"]){
  color: red;
}
[random-attribute~="value"] h2{
  color: blue;
}
<div class="content">
  <h2>Same valid selector, not working</h2>
  <div random-attribute="value">
      <h2>Valid selector turned blue.</h2>
  </div>
</div>

You are only supposed to put the given attribute in :not(), not the actual element.

Arnav Borborah
  • 9,956
  • 4
  • 32
  • 69
  • 1
    But that'e an entirely different thing. That's looking for any `h2` element that doesn't have `random-attribute="value"` in it. I want any `h2` element that is not a child of anything with a `random-attribute="value"` – leigero Oct 18 '16 at 18:08
  • 2
    @leigero then change it to match the divs https://jsfiddle.net/1yz3nw7p/ – DaniP Oct 18 '16 at 18:10
1

In Selectors Level 3, :not only supports a simple selector argument. That will probably change in Selectors Level 4, but browsers don't support it yet.

The negation pseudo-class, :not(), is a functional pseudo-class taking a selector list as an argument. It represents an element that is not represented by its argument.

Note: In Selectors Level 3, only a single simple selector was allowed as the argument to :not().

Meanwhile, you can rewrite

h2:not([random-attribute~="value"] h2)

as

:root:not([random-attribute~="value"]) > h2,
:root:not([random-attribute~="value"]) > :not([random-attribute~="value"]) > h2,
:root:not([random-attribute~="value"]) > :not([random-attribute~="value"]) > :not([random-attribute~="value"]) > h2
/* ... repeat until you get deep enough */

However, instead of using complicated selectors like that, in CSS it's more natural to let the cascade pick the most specific styles. As kristóf baján recommends, you don't even need :not:

h2 {
  /* Default styles */
}
[random-attribute~="value"] h2 {
  /* Overriding styles */
}
Oriol
  • 225,583
  • 46
  • 371
  • 457
0

I think you are making your job a little too complicated... :) You should just use:

[random-attribute="value"] h2{
...
}
h2 {
...
}

This should solve your problem. The reason behind the fact that it is not working as YOU would expect it to is that the selector inside the not operator is supposed to extend the clarification of the element and not its parent.

kristóf baján
  • 383
  • 1
  • 3
  • 14