791
votes

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?

5
"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: stackoverflow.com/questions/10711730/… (the answer also mentions that article on the side)BoltClock♦
Congratulations! You have successfully written valid CSS4.0 in your example above 2 years before the official edition came out.Jack Giffin
@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: w3.org/TR/2011/WD-selectors4-20110929/#negation And it pre-dates the first implementation by 4 and a half years: stackoverflow.com/questions/35993727/…BoltClock♦
According to MDN, the :not() selector with multiple arguments, is currently supported in FF84 and Safari9: developer.mozilla.org/en-US/docs/Web/CSS/:not#specificationskunambi

5 Answers

1601
votes

Why :not just use two :not:

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

Yes, it is intentional

52
votes

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*/
}
35
votes

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 limited. For now, it only works in Safari.

10
votes

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.

6
votes

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