Search code examples
csspseudo-class

What is the expected behavior when "!important" is used with the pseudo-class ":not"


I'm cleaning up someone else's code and it basically looks like this:

a {color:red;}
#contentdiv :not(h4) > a {color:green!important}

So all links are green, except for those under an h4 which are red.

Suppose all links under "li"s need to be red too. Better yet, suppose the links under "li"s need to inherit whatever is input by the user in this particular CMS, so the color can change without declarations in a stylesheet.

In other words...

#contentdiv ul li a {color:red!important}

...wouldn't work because when the global style on "a" tags changes, the "a" tags under the "li"s would remain red.

However trying to negate the "!important" like...

a {color:red;}
#contentdiv :not(h4) > a,
#contentdiv :not(li) > a {color:green!important}

...just seems to cancel out both negations. I know the ":not" pseudo should work like "(!A and !B)" but adding the important seems to make it target A or B complement "(A/* or B/*)" which means everything turns green, even the "a" tags under the "h4"s and "li"s.

Here's a JSFiddle: https://jsfiddle.net/qebz4bbx/2/

Just looking for some clarification on this. Thanks!


Solution

  • You misunderstood the comma ,.

    The comma is a logical OR, not a logical AND.

    Therefore,

    #contentdiv :not(h4) > a,
    #contentdiv :not(li) > a
    

    matches every element which

    • Is an a element, its parent is not a h4 element, and that parent is a descendant of an element with id="contentdiv".
    • OR
    • Is an a element, its parent is not a li element, and that parent is a descendant of an element with id="contentdiv".

    Therefore, your selector is equivalent to #contentdiv * > a.

    Instead, you should use

    #contentdiv :not(h4):not(li) > a
    

    That matches every a element whose parent is neither a h4 element nor a li element, and that parent is a descendant of an element with id="contentdiv".