Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I override a selector with many negations (:not)?

For example to style standard inputs I write something like:

input:not([type="checkbox"]):not([type="radio"]) {
    background-color: blue;
}

However that increases the specificity a lot so if I want to override it using a class I have to do something like:

.red.red.red {
    background-color: red;
}

Is there a way to decrease the specificity of the original input selector without changing the functionality?

like image 448
joshhunt Avatar asked Mar 08 '17 20:03

joshhunt


2 Answers

Unfortunately, in Selectors 3, that's the best you can do since :not() only accepts a single simple selector. Having said that, the selector in your overriding rule can be replaced with input.red.red — you don't need more class selectors than attribute selectors unless that rule has to appear earlier in the stylesheet.

This is another problem that Selectors 4 solves with its enhancement of :not(): specificity. In Selectors 4, you will be able to replace all those negations with just one :not() pseudo, effectively decreasing its specificity within your original selector to just one attribute selector. From section 16:

The specificity of a :not() pseudo-class is replaced by the specificity of the most specific complex selector in its selector list argument.

Since any attribute selector is equally specific to a class selector, the specificity of any number of lone attribute selectors in a list will never be more than that of just one of them. This allows you to get away with using just one class selector for your override without having to repeat it.

The following works in Safari as a proof-of-concept:

/* 1 type, 2 attributes -> specificity = (0, 2, 1)
input:not([type="checkbox"]):not([type="radio"]),
   1 type, 1 attribute  -> specificity = (0, 1, 1) */
input:not([type="checkbox"], [type="radio"]) {
    background-color: blue;
}

/* 1 type, 1 class      -> specificity = (0, 1, 1) */
input.red {
    background-color: red;
}
<input type="checkbox">
<input type="radio">
<input type="text">
<input class="red" type="text">
like image 119
BoltClock Avatar answered Oct 01 '22 09:10

BoltClock


This may get you around the specificity issue:

input:not([type="checkbox"]):not([type="radio"]):not(.red)) {
    background-color: blue;
}

.red {
  background-color: red;
}
<input type="checkbox"><br>
<input type="radio"><br>
<input class="red">
like image 32
Michael Benjamin Avatar answered Oct 01 '22 11:10

Michael Benjamin