How to Fix CSS @supports "not" Operator Not Working With "and" or "or"?

To figure out why the not operator might not be working with and and/or or operators in your CSS @supports query, you can check for the following:

  1. Missing Whitespace;
  2. Invalid Use of Parentheses;
  3. Browser Support.

Check for Missing Whitespace

Whitespace is required after not and on both sides of and or or. Therefore, as a first step, please make sure you're following the correct syntax.

Check for Invalid Use of Parentheses

A layer of parentheses must be added when mixing and, or, and not operators based on the following rules:

  • When combining and and or you must wrap them in parentheses to define the order in which they apply, otherwise the whole rule is ignored;
  • When using not with and or or, you must wrap the entire not expression in parentheses (unless it exists on its own at the top level). Otherwise, the whole rule is ignored.

Keeping that in view, consider the following examples:

Combining not With and:

To check if one property/value is supported while the other is not, you can do the following:

@supports (...) and (not (...)) { /* ... */ }

Notice the use of parentheses around the whole not expression. You may reverse the order of the two expressions, but you will still have to wrap the entire not expression in parentheses. For example:

@supports (not (...)) and (...) { /* ... */ }

You may negate an entire expression (in which case you do not need to wrap the not within parentheses, as it exists on its own at the top level):

@supports not ((...) and (...)) { /* ... */ }

Combining not With or:

Same rules apply as with combining not with and. For example, to check if a property/value pair exists, or another pair that does not exist, you can do something like the following:

@supports (...) or (not (...)) { /* ... */ }

Notice the use of parentheses around the whole not expression. You may reverse the order of the two expressions, but you will still have to wrap the entire not expression in parentheses. For example:

@supports (not (...)) or (...) { /* ... */ }

You may negate an entire expression (in which case you do not need to wrap the not within parentheses, as it exists on its own at the top level):

@supports not ((...) or (...)) { /* ... */ }

Mixing not, and and or:

When mixing an arbitrary number of conjunctions (and), disjunctions (or), and/or negations (not) in a single @supports query, you need to make sure you use parentheses correctly. In the following example for instance, either the first expression containing not and and should be true, or the second expression:

@supports ((not (...)) and (...)) or (...) { /* ... */ }

Based on the rules about parentheses, in the example above you can see:

  1. How the not expression is wrapped in parentheses (as it is being mixed with the and operator), and;
  2. How the first expression itself is wrapped in parentheses to define the order of precedence between the conjunction (and) and disjunction (or).

Similarly, you can combine not and or as well. For example, in the following @supports query, the first expression containing not and or should be true, as well as the second expression:

@supports ((not (...)) or (...)) and (...) { /* ... */ }

However, when the not operator exists on its own at the top level, you do not need to wrap the negation in parentheses (as shown below):

@supports not ((...) and ((...) or (...))) { /* ... */ }

Check for Browser Support

If the first two steps don't resolve the problem for you, then it could be that the browser you're testing on does not support @supports. Have a look at the browser support chart for @supports to be sure.


This post was published by Daniyal Hamid. Daniyal currently works as the Head of Engineering in Germany and has 20+ years of experience in software engineering, design and marketing. Please show your love and support by sharing this post.