842

I'm trying to select input elements of all types except radio and checkbox.

Many people have shown that you can put multiple arguments in :not, but using type doesn't seem to work anyway I try it.

form input:not([type="radio"], [type="checkbox"]) {
  /* css here */
}

Any ideas?

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
delphi
  • 10,705
  • 5
  • 22
  • 18
  • 25
    "Many people have shown that you can put multiple arguments in :not" Either those people were quoting a certain article that is popularly referenced but gravely misleading, or they were talking about jQuery, not CSS. Note that the given selector is in fact valid in jQuery, but not in CSS. I wrote a Q&A detailing the differences: http://stackoverflow.com/questions/10711730/why-is-my-jquery-not-selector-not-working-in-css (the answer also mentions that article on the side) – BoltClock Jun 17 '14 at 15:27
  • 13
    Congratulations! You have successfully written valid CSS4.0 in your example above 2 years before the official edition came out. – Jack G Aug 03 '17 at 23:51
  • 2
    @Jack Giffin: What "official edition" are you referring to? This question only pre-dates the FPWD of selectors-4 by 5 months, and the spec is still nowhere near completion: https://www.w3.org/TR/2011/WD-selectors4-20110929/#negation And it pre-dates the first implementation by **4 and a half years**: https://stackoverflow.com/questions/35993727/not-selector-not-behaving-the-same-between-safari-and-chrome-firefox/35993791#35993791 – BoltClock Apr 13 '20 at 05:03
  • According to MDN, the :not() selector with multiple arguments, is currently supported in FF84 and Safari9: https://developer.mozilla.org/en-US/docs/Web/CSS/:not#specifications – kunambi Jan 09 '21 at 16:45

5 Answers5

1677

Why :not just use two :not:

input:not([type="radio"]):not([type="checkbox"])

Yes, it is intentional

TylerH
  • 20,799
  • 66
  • 75
  • 101
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • 9
    This has a high specificity. – Undistraction Mar 05 '15 at 15:50
  • 92
    For those who don't get the humor: he said "Why not..." with the `:` character. – totymedli Dec 08 '15 at 20:00
  • Can we do this for parent? eg `h1:not(body.home &)` ? – w3debugger Feb 16 '16 at 13:39
  • 16
    As a side note, if you do something like `input:not('.c1'), input:not('c2')` you end up with an "and" situation where both classes would have to be on the input for it to match. – Cloudkiller Mar 11 '16 at 16:49
  • @sircapsalot not work in safari 9.1.1 Please use double `not` like answer. – Penguin May 27 '16 at 08:46
  • 6
    @BoltClock Delayed, but, hence the desire for the `:not([attr],[attr])` CSV format as well :-P – TylerH Feb 20 '17 at 15:12
  • :note, it needs to be a:not(X):not(Y), you can't put a space between : or else it won't work. – Dmytro Apr 28 '18 at 18:00
  • 7
    @Cloudkiller no that would select any input element -> "input without the class c1 OR input without the class c2" – David Callanan Jan 10 '19 at 14:57
  • 2
    @DavidCallanan You'd think right? But it does act as AND. Can't quite grok why. – Dakota Trotter May 07 '19 at 21:25
  • @Cloudkiller a) I believe the format you wrote is wrong, (should be without single quotes and c2 is missing `.`) b) it's NOT an "AND" situation, but a **NAND** situation - the CSS is NOT applied only if BOTH classes are present on the element. (I think correct format would be `input:not(.c1), input:not(.c2)`) – jave.web Oct 12 '20 at 22:02
  • 1
    @DakotaTrotter it's not `AND` but `NAND` as I mentioned above ^, but the reason behind is that selectors of 1 CSS block are NOT additive, meaning each acts on it's own - one is ONLY excluding `.c1`, the other one is ONLY excluding `.c2`, therefore element that should NOT match those selectors should be against both - so it either has to be not an input or meat the not exclusion for both selectors - is it clearer now ? :) – jave.web Oct 12 '20 at 22:06
  • @Cloudkiller You have it the other way around. If either `.c1` or `.c2` are missing, it'll match the selector. If both are present, it'll skip it. – Drazen Bjelovuk Feb 10 '22 at 17:53
53

If you're using SASS in your project, I've built this mixin to make it work the way we all want it to:

@mixin not($ignorList...) {
    //if only a single value given
    @if (length($ignorList) == 1){
        //it is probably a list variable so set ignore list to the variable
        $ignorList: nth($ignorList,1);
    }
    //set up an empty $notOutput variable
    $notOutput: '';
    //for each item in the list
    @each $not in $ignorList {
        //generate a :not([ignored_item]) segment for each item in the ignore list and put them back to back
        $notOutput: $notOutput + ':not(#{$not})';
    }
    //output the full :not() rule including all ignored items
    &#{$notOutput} {
        @content;
    }
}

it can be used in 2 ways:

Option 1: list the ignored items inline

input {
  /*non-ignored styling goes here*/
  @include not('[type="radio"]','[type="checkbox"]'){
    /*ignored styling goes here*/
  }
}

Option 2: list the ignored items in a variable first

$ignoredItems:
  '[type="radio"]',
  '[type="checkbox"]'
;

input {
  /*non-ignored styling goes here*/
  @include not($ignoredItems){
    /*ignored styling goes here*/
  }
}

Outputted CSS for either option

input {
    /*non-ignored styling goes here*/
}

input:not([type="radio"]):not([type="checkbox"]) {
    /*ignored styling goes here*/
}
Daniel Tonon
  • 9,261
  • 5
  • 61
  • 64
  • 10
    isn't that kinda like asking a lumberjack to go to the hardware store instead to get his wood? – osirisgothra Jun 16 '15 at 10:43
  • What? so you would rather write .selector:not(.one):not(.two):not(.three):not(.four) { ... } than .selector { @include not('.one','.two','.three','.four') { ... } } ? – Daniel Tonon Jun 30 '15 at 07:05
  • 2
    In terms of efficiency: [yes.](http://puu.sh/kkfuB/93b41e8496.png) Way less `'` characters and imo more efficient code. – Daan Sep 22 '15 at 15:00
  • `:not()` = 6 characters per item; `'',` = 3 characters per item. `@include` should be assigned to a hot key so I'm going to count that as one character (in terms of typing it). Technically I don't think you even need to use the single quote marks in the list if you hate them that much. They do help prevent editors from freaking out though. Based on that, I still think my way is the more typing efficient way of writing it out. – Daniel Tonon Sep 23 '15 at 02:09
  • 2
    @DaanHeskes also that writing out all the :not() cases doesn't allow you to use a variable to list them. – plong0 Jan 18 '16 at 21:03
  • I still don't understand why anyone uses SASS. It's like you want to type less just to produce more code, so arguing over a few bytes doesn't make a whole lot of sense. – Eyelash Jul 08 '18 at 21:04
53

Starting from CSS Selectors 4 using multiple arguments in the :not selector becomes possible (see here).

In CSS3, the :not selector only allows 1 selector as an argument. In level 4 selectors, it can take a selector list as an argument.

Example:

/* In this example, all p elements will be red, except for 
   the first child and the ones with the class special. */

p:not(:first-child, .special) {
  color: red;
}

Unfortunately, browser support is somewhat new.

vsync
  • 118,978
  • 58
  • 307
  • 400
Pieter Meiresone
  • 1,910
  • 1
  • 22
  • 22
10

I was having some trouble with this, and the "X:not():not()" method wasn't working for me.

I ended up resorting to this strategy:

INPUT {
    /* styles */
}
INPUT[type="radio"], INPUT[type="checkbox"] {
    /* styles that reset previous styles */
}

It's not nearly as fun, but it worked for me when :not() was being pugnacious. It's not ideal, but it's solid.

eatCasserole
  • 109
  • 1
  • 3
6

If you install the "cssnext" Post CSS plugin, then you can safely start using the syntax that you want to use right now.

Using cssnext will turn this:

input:not([type="radio"], [type="checkbox"]) {
  /* css here */
}

Into this:

input:not([type="radio"]):not([type="checkbox"]) {
  /* css here */
}

https://cssnext.github.io/features/#not-pseudo-class

Daniel Tonon
  • 9,261
  • 5
  • 61
  • 64
  • Would like to follow the link and buy the "plugin" advertised here, but (un)fortunately the target site seems to be unavailable anymore. – blerontin Dec 02 '20 at 13:21
  • Thanks for letting me know the link was broken. CSS Next have changed their URL since I posted my answer. I've fixed the links now. You didn't have to be so sassy about it though. It's a free open-source Post-CSS plugin. Would you be this sassy if I posted a link to something like Lodash or Bootstrap? – Daniel Tonon Dec 02 '20 at 22:24