not(.MyClass) selector with important

I am adding a fiddle below that gives a visual on the matter I’m dealing with. While messing around with css selectors I’ve realized that the !important selector is very strong, until it meets its boss the :not selector.

  background-color:green !important;

In my fiddle I declared an initial value of purple to all my backgrounds. I ordered the first one specifically to be red and the second one to be blue I then ordered all my backgrounds except red to be green. It did so!

Good so far - then I made a brown, and the another brown with a change of color to purple important. It changed both brown classes.

The confusing came about these two browns not turning green when I specifically demanded that all except red must be green! I said to myself, “the important selector sure it’s strong!” Then I added an !important selector to my :not selector class for good measure. Given that the purple Important class is the bottom-est class, it will overwrite the Important on the Green and remain purple….OOOOHHHHH NOOOOOO!!!! They all (except red) turned GREEN!

What gives? What is the true hierarchy and chain of command on css selectors?

Here is the FIDDLE


It’s basically because of the selector’s specificity.

According to MDN,

The specificity of the :not pseudo-class is the specificity of its argument. The :not pseudo-class does not add to the selector specificity, unlike other pseudo-classes.

Therefore the selector div:not(.red) is more specific than .brown regardless of order: (example)

div:not(.red) {
  background-color:green; /* Still applied */
.brown {
  background-color:purple; /* Overwritten - even though this appears last */

The same thing happens when we add in !important to the declaration: (example)

div:not(.red) {
  background-color:green!important; /* Still applied */
.brown {
  background-color:purple!important; /* Overwritten - even though this appears last */

However, if we increase the specificity of .brown by adding in the type, (div.brown), its background color will be applied. (example) Both selectors now have the same specificity, therefore the same thing occurs when !important is added to both. (example) At this point, it all comes down to order.

div:not(.red) {
div.brown {
  background-color:purple; /* This is applied now */
} /* ..even if both declarations have !important */

It’s important to note that !important doesn’t increase the specificity of a selector. Instead, it just changes the cascade nature in determining which declarations are applied. For a great, detailed answer explaining this, see this answer by BoltClock.