Can the :not() pseudo-class have multiple arguments? - css

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?

Why :not just use two :not:
input:not([type="radio"]):not([type="checkbox"])
Yes, it is intentional

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

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.

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.

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

Related

How I exclude more than one element with CSS selector group? [duplicate]

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?
Why :not just use two :not:
input:not([type="radio"]):not([type="checkbox"])
Yes, it is intentional
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*/
}
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.
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.
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

Less code for '+' css selector

I was working with custom radio buttons and checkboxes, the css is vast so I want to convert it to less way of organizing but how can I convert this statement to less
input[type='checkbox']:checked + .mycheck-overlay:before{
/*some css*/
}
any help would be greatfull....
It depends how you want to structure your LESS, the following is still valid, if you dont need any styling for the intermediate sections.
input[type='checkbox']:checked + .mycheck-overlay:before{
/*some css*/
}
However, depending on exactly which section of the rule you wish to style, in full you can break it down thusly:
input[type='checkbox']{
/* normal checkbox styles */
&:checked{
/* checked state checkbox styles */
+ .mycheck-overlay{
/* style of elements with class mycheck-overlay immediately after a checked input checkbox */
&:before{
/* the before psuedo styling for those... */
}
}
}
}
Note that you can use the ampersand & character preceding a nested rule to indicate it should be applied in conjunction with the parent selector (i.e. when the rule is compiled, no space should be left between it and the preceding selector)

Inherit attributes from another object in css

I have a class in my css called .btn:
.btn {
//stuff here
}
and I am going to create another class, lets say .btn2. I want to be able to inherit the characteristics from .btn into btn2, as I only want to change the color of button 2. Is there a way in CSS for this? Or should I just copy and paste the original stuff into the new class?
I'd suggest:
/* comma-separated selectors: */
.btn,
.btn2 {
/* shared properties */
}
.btn2 {
/* properties unique to btn2 */
}
JS Fiddle demo.
You can do it with dynamic stylesheets. Check out LESS or SASS.
EDIT:
Some additional info at a commenter's request. Here are the official sites. They both have examples on their home pages.
http://lesscss.org/
http://sass-lang.com/
What you can do is this
.btn, .btn2 {
/* Styles goes here */
}
This way, both the classes will share common properties defined in the rule block.
As far as the inheritance goes, something you would like to have..
.btn2 {
.btn; /* Won't work in pure CSS */
}
Won't work in pure CSS, you need to take a look at SASS or LESS

Middle Child Pseudo-Class

Is there a way to use CSS selectors to get the middle child in a list of elements?
I know that there is no literal :middle-child selector, but is there another way without resorting to Javascript?
This has been working well for me:
*:not(:first-child):not(:last-child) {
...
}
You can see an example of this here: http://codepen.io/bentomas/pen/Gwqoe
The one caveat to this is that it only works in IE 9+: http://caniuse.com/#feat=css-sel3
While not elegant, if you know the upper and lower limits of the total number of elements, you could take a brute force approach to select the middle element.
For example, the following rules will select the middle element in a set of 5, 7, or 9 elements.
div:nth-child(3):nth-last-child(3) {
/* The middle element in a set of 5 is the 3rd element */
}
div:nth-child(4):nth-last-child(4) {
/* The middle element in a set of 7 is the 4th element */
}
div:nth-child(5):nth-last-child(5) {
/* The middle element in a set of 9 is the 5th element */
}
Or with Sass:
#for $i from 3 through 5 {
div:nth-child(#{$i}):nth-last-child(#{$i}) {
/* The middle element */
}
}
You can use the "not first and not last" approach, like so:
CSS
li:not(:first-child):not(:last-child) {
color:red;
}
HTML
<ul>
<li>First</li>
<li>Second</li>
<li>Third</li>
</ul>
Check the JsFiddle
If you want to apply a style to all elements that are neither first children nor last children, you could use :not(:first-child), apply the style, and then use :last-child to 'take the style away' from the last element. But you'd have to think about what happens when there are less than 3 elements.
I've encountered the need to target the middle child on several occasions, and I've taken to using this sass mixin I wrote after referencing many similar questions, and their respective answers.
// Generate a reasonable number rules limited by $n.
#mixin middle-child($n) {
// There is no middle for nChildren less than 3,
// so lets just start at 3.
#for $i from 3 to $n {
// Find the middle, bias right for odd numbers.
$mid: math.ceil(math.div($i, 2));
// Select only those sets of children that number $i.
&:first-child:nth-last-child(#{$i}) {
// Select the middle child of that set.
~ :nth-child(#{$mid}) {
#content; // Apply your styles.
}
}
}
}
Usage:
.navigation {
background-color: #ba0020;
.nav-item {
color: white;
#include middle-child( 8 ) {
font-weight: 900;
}
}
}
Have you tried :nth-child(#) ?
Depending on which one you want to select you just replace # with the number.
Javascript is the only way to do this client side.

Declare a global CSS property ? Is this possible?

I have a very wierd question, I dont know wether if its possible in css or not
Suppose I have say 3 different css classes as shown below, as you can see I have a common property of all these classes, I want to declare this color somewhere else and pass a reference to it here, so if next time I want to change the color I can simply change at one place rather than changing in all the 5 classes.
I know that you can use body{}, or a wrapper for this but that would affect the colors of the entire site right ? Is there a way to do this ?
Is this even possible ?
.abc {
color:red;
}
.abc2 {
color:red;
}
.abc3 {
color:red;
}
.abc4 {
color:red;
}
.abc5 {
color:red;
}
The bad news: you can't do it in CSS.
The good news: you can write in a meta-CSS language like LESS, which then processes a LESS file to pure CSS. This is called a "mixin".
In LESS:
#errorColor: red;
.error-color {
color: #errorColor;
}
#error-1 {
.error-color;
}
.all-errors {
.error-color;
}
More info: http://lesscss.org/#-mixins
if you want to declare all of them at a time, you can use:
.abc, .abc2, .abc3, .abc4, .abc5 {
color:red;
}
Or you can declare an additional class & add to all the .abc, .abc2.... & make its color:red;.
This can not be done with CSS, but that is still a very popular thing to do by using a CSS preprocessor such as LESS, SASS, SCSS, or Stylus.
A preprocessor will let you define a variable (say $red = #F00). It will replace the variable in your CSS document with the variable value for you, allowing you to write very DRY and module CSS.
This functionality is referred to as "CSS variables", which is part of the future spec, but not yet implemented on any browsers.
For now, the best way to do this in pure CSS is to declare an additional class for the desired "global", and then add that class to all relevant items.
.abc_global { color: red; }
.abc1 { /* additional styling */ }
.abc2 { /* additional styling */ }
<div class="abc1 abc_global"></div>
<div class="abc2 abc_global"></div>
With LESS
You are able to define that red color once:
.myRedColor {
color:red;
}
Now you can call that red on any CSS styles. Even NESTED styles! It's a wicked tool!
.abc1 {
.myRedColor;
}
.abc2 {
.myRedColor;
}
.abc3 {
.myRedColor;
}
.abc4 {
.myRedColor;
}
NESTED EXAMPLE:
.abc {
.itsEasyAsOneTwoThree{
.myRedColor;
}
}
Now all of our "itsEasyAsOneTwoThree" classes that are properly nested inside of an "abc" class will be assigned the red style. No more remembering those long #867530 color codes :) How cool is that?!
You can also use PostCSS with the plugin postcss-preset-env and support custom properties/variables, then use the :root selector to add global css variables.
:root {
--color-gray: #333333;
--color-white: #ffffff;
--color-black: #000000;
}

Resources