Can CSS pseudo-classes be used inside of the :not() pseudo-class? - css

I was wondering if its possible to "embed" pseudo-classes inside of each other. I have a hunch that you can't, but I just want to make sure I don't just have syntax wrong.
Here's an example of what I'm trying to do:
p.description { margin-bottom: 20px; }
Given that style, if you only want that to happen on matches that aren't the LAST p.description, is there anyway to do the following?
p.description:not(p.description:last-child)
Naturally, I'd have two styles, like so:
p.description { margin-bottom: 20px; }
p.description:last-child { margin-bottom: 0; }
...but that seems wasteful if it can be done in a single line.
Thanks a lot!

Yes, to the title of your question:
p.description:not(:last-child)
No, to the CSS example in the body of your question
p.description:not(p.description:last-child)
The spec says:
The negation pseudo-class, :not(X), is a functional notation taking a simple selector (excluding the negation pseudo-class itself) as an argument.
A simple selector is either a type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class.

Yes, p.description:not(:last-child).

Yes you can, in webkit it works fine. I use this for example:
.middlenav:not(:nth-last-child(1))
Works great.
so p.description:not(:last-child).
should too

Related

Why does putting comma selectors inside a space selector break the parent?

I am used to using descendant space selectors and comma selectors. I have ids around larger sets of elements in order to manipulate them easier in jquery and css.
So I tried something like this:
#parent_id input, textarea
{
width: 100px;
}
So when I do this, my expectation is that this effect will occur on input AND textarea inside the #parent_id. Instead, this disqualifies parent_id and just selects all input, textarea. Why? And how can I avoid this, aside from making them separate.
In CSS, rules have the form:
selector0 [, selectorN ]*
{
property0: value0[,
property1: value1]*
}
So the comma , is used to separate different selectors for the same property set. For example, if you wanted two radically different selectors for the same property set.
Selectors in CSS must be fully-qualified, there is no contextual-sensitivity - this is partly because CSS is designed to be forward-compatible: browsers are instructed to try each and every selector in a rule independently, so browsers gracefully-degrade when they encounter new selector syntax they don't support.
To get the effect you want just type more :)
#parent_id input,
#parent_id textarea {
width: 100px;
}
Note that there is a proposed/experimental :matches() selector function which works as a logical OR operator in selectors, it's in the CSS Level 4 Selectors specification (currently in a working-draft state, as of 2016-05-04: https://drafts.csswg.org/selectors-4/ ).
The matches-any pseudo-class, :matches(), is a functional pseudo-class taking a selector list as its argument. It represents an element that is represented by its argument.
So in your case it would be:
#parent_id :matches( input, textarea ) {
width: 100px;
}
But I don't think this usage is really that better, it's less obvious and requires greater knowledge of CSS.

What does the CSS `not` selector do?

I saw the following snippet in a css file. What does it do?
h3 ~ *:not(h3) {
margin-left: 15px;
}
Obviously it alters h3 headers in some way but I don't understand what ~ *:not(h3) does.
Googling ~ *:not(h3) is unproductive.
The isn't HTML. It is a CSS selector.
Specifically, it is the negation pseudo-class:
The negation pseudo-class, :not(X), is a functional notation taking a simple selector (excluding the negation pseudo-class itself) as an argument. It represents an element that is not represented by its argument.
Obviously it alters h3 headers
No, it does exactly the opposite. It stops the selector from matching h3 elements.
This is CSS, not HTML. See Mozilla's documentation on the CSS negation pseudo class for more details, but not basically selects elements that do not match the specified selector (in this case, h3).

CSS grouping :hover & :active

When I want to define css selector with :hover and :active I have to do:
#mainPage #content div.group:hover, #mainPage #content div.group:active {}
As one can see it contians repeated #mainPage #content div.group and can get messy. Is there a way to group it somehow like:
#mainPage #content div.group:hover:active {}
In pure CSS there is not much of a better way to handle both more succinctly without adding a class or ids.
You could consider a CSS pre-compiler (like LESS or SASS/SCSS).
In LESS or SCSS:
#mainPage #content div.group {
&:hover, &:active {
color: red;
}
}
I suggest add ID for the element has class group and write below code will reduce the effort:
#idname.group:hover, #idname.group:active{}
Is there a reason why you're using #mainPage #content before div.group?
Generally, it's not necessary to add that much 'specificity' to your selectors - it's better to instead, have unique classes. So make sure that the class .group is only used for elements that you want to have the same styles.
If you do that, you should be able to style those elements just using
.group { styles here}
You might run into an issue now where if you try to override any of the styles you set like #mainPage #content, those will be more specific and so in effect 'stronger' than styles where you don't use the full list of parents. If possible, change all your styles not to include the parent elements - this is also worthwhile in case you ever want to move an object to a different part of the html!
It's also, in general, advisable not to use id's (#name) to attach css styles - if possible, just use classes. Unless you're doing javascript, you shouldn't have much need for id's.
Obviously there exceptions to the above, and for all I know you may have a perfectly good reason for doing things the way you have - in which case SASS (as suggested in a few other answers) is a good solution for you.
If not useful for you, I hope at least this answer might be useful for someone who might come along later - I've noticed that a lot of people newer to css don't realize how specificity of selectors works and end up making their styles a lot more complicated than necessary as a result! :)
Old question, but this should be relevant for somebody who needs this.
Pseudo-class released by the end of 2020
You can use :is() pseudo-class like so :
#mainPage #content div.group:is(:hover, :active) {
}
Here is a little snippet to picture it :
a:is(:hover, :focus) {
color: red;
outline: #5bc8ea dotted 4px;
outline-offset: 4px;
font-weight: 600;
}
Hover/Focus me
More informations about :is() pseudo class here: https://developer.mozilla.org/en-US/docs/Web/CSS/:is and here: https://css-tricks.com/almanac/selectors/i/is/.
Works with most of the popular browsers (incompatible with IE, Opera and Safari < 14) https://caniuse.com/css-matches-pseudo.
It surely is more often used to select elements than pseudo-classes like :hover or :focus but it will do the trick as I can't see any other solution for now.
Why you use #mainPage #content? #content should be enough to find the div your looking for without the #mainPage.
Also id's are only allowed to be used once and not in multiple places like classes are. Id's are usually reserved for script assignments and not CSS. I would do
#content .group:hover{}
#content .group:active{}
if i understood correctly, you want a group of elements to act a certain way? manipulate the parent class then.
.parent-class:hover {
.child-class {
…desired styles go here
}
}

Do I need to repeat common portions of a selector or is there a nicer way?

I want to have something like the following (like a || ):
[.pw-each-placecomment or .pw-each-usercomment] h2 { }
Is this possible?
Not with plain CSS right now. Firefox has introduced the non-standard :any(), but it's experimental and only in Firefox, Chrome and Safari. It may make it in as :matches(), so keep an eye on it.
If you don't use a CSS preprocessor, such as SASS, Stylus, LESS, etc, you're tough out of luck.
You'll have to list 'em both out.
.pw-each-placecomment h2,
.pw-each-usercomment h2 {
}
You could use the attribute selector.
The ^ (carat) symbol indicates the beginning of a string (here- the beginning of the class name):
div[class^="pw-each-"] h2 {
color: red;
}
FIDDLE
This would select any h2 element with an ancestor div with a class name that starts with "pw-each-"
So for example: pw-each-placecomment and pw-each-usercomment - would match... but
pw-other-other or other-pw-each-placecomment- wouldn't.
For more info about this selector (and selectors in general) - I recommend this article

CSS Selector for not a child of element type?

I want to style code elements that are not inside a tags.
What is the best approach to accomplish this?
code:not(a code) doesn't seem to work at all, at least on Chrome, even though it seems like it should
I can't get it to work from the console either.
Are there any other css-only approaches I could use for this?
:not does not support combinator selectors.
If we're talking about its direct parent:
:not(a) > code
Otherwise there's no way to do this in CSS. You'll have to override it:
code {
/* some styles */
}
a code {
/* override previous styles */
}
Actually, you should be able to use your code đŸ¤”, or you could use the wildcard character to select all elements to not be selected
code:not(a *) {
font-weight: bold;
}
Codepen

Resources