With the proliferation of design libraries in order to reduce bugs within the UI, create a more consistent user experience, and increase developer velocity in order to get features shipped faster, it’s common to have CSS stylesheets that are more generic in nature.

However, like most things, there are times when exceptions to the general rules need to be made, and trying to keep those exceptions managable as the library evolves can be a challenge at times.

One of these exceptions can come in the form of wanting to remove CSS rules applied by a more generic selector for a specific use case.

One common approach is to increase the rule specificity, and ensure that the more specific rule is evaluated prior to the more generic one. The more specific rule would likely have to live on the same level as the generic rule, such as in the example below, where fill: black is being omitted on .the-specific-icon-class-style:

.the-generic-icon-class-style .the-specific-icon-class-style {
  padding: 8px;
}

.the-generic-icon-class-style {
  fill: black;
}

The benefit of the specificity approach is that incompatabilities with older browsers is less of a concern, and the rule applies to any element that matches.

The drawback to this approach is that if this happens enough times, with different omissions being performed for different exceptions, the CSS file will likely start to become a little cumbersome.

However, an alternative approach that can be taken that can result in a cleaner solution is the :not CSS pseudo-class. Building on the example above, the CSS would look something like the following:

.the-generic-icon-class-style {
  padding: 8px;

  &:not(.the-specific-icon-class-style) {
    fill: black;
  }
}

The benefit to this approach is that the CSS is written much like other rules where the desire is to inherit the parent rules and apply additional ones to a more specific class except in this case, we’re wanting to ensure that the rule is omitted from .the-specific-icon-class-style rather than added on.

There are a few drawbacks to this approach though. The :not pseudo-class has some quirks to it, which are outlined in the MDN documentation for this pseudo-class. Among them, you can perhaps mistakenly match on <html> and <body> tags, or that the selector only applies to a single element and can’t be used to exclude all ancestors of an element 1.

Additionally, if you need to support IE 11 for your website, only the base use case of the :not pseudo-class is supported (what’s seen in the example above). This removes the ability to be able to use more powerful aspects of the pseudo-class, such as providing a list of classes to apply the :not to 2.

To conclude, the :not pseudo-class is a great choice if there is a relatively simple use case where the desire is to remove rules rather than add more on, and can be incredibly powerful when used correctly. However, the more powerful aspects of :not are only available in more modern web browsers, and in complex scenarios, the use of :not may introduce strange outcomes that can be difficult to debug based on how the evaluations for the pseudo-class are performed.


  1. https://developer.mozilla.org/en-US/docs/Web/CSS/:not ↩︎

  2. https://css-tricks.com/almanac/selectors/n/not/ ↩︎