CSS :not() selector affects other elements, what am I missing? - css

I have the following test code:
<html>
<head>
<style type="text/css">
#test, .random-class { font-weight:bold; }
#test, .random-class:not('.another-class') { color:red; }
</style>
</head>
<body>
<div id="test">hello world</div>
</body>
</html>
This produces the following output:
In my understanding, hello world should be bold and red, but it's only bold.
I expected the second rule to affect
the element with id test OR
any element with class .random-class and not class .another-class
What am I missing here? Why is the second rule not applied?

You don't need the quotes around the class in your :not() selector, if you change it so it becomes:
#test, .random-class:not(.another-class)
{
color:red;
}
It will work as you expect it to
Take a look here for a demo
Take a look here for the docs on the :not() selector
Mentioned by #KWeiss in the comments:
Specifically the quotes are making the selector invalid so the rule is not applied
Hope this helps!

You dont need to use ' in :not
#test, .random-class { font-weight:bold; }
#test, .random-class:not(.another-class) { color:red; }

The second rule is not applied because there's an error in your sytax, which breaks the entire rule, not just the selector that is broken.
:not(.abother-class) is teh correct syntax (without the quotes.
If you separated your rules into two you'd get your desired effect, as would fixing the error e.g. either of these two solutions should work:
#test {color: red}
.random-class:not('.another-class') {color: red} /*This is still broken, but doesn't effect the above rule now*/
or
#test, .random-class:not(.another-class) {color: red} /* fixed*/

Related

How to edit :After-Content() when hovering? [duplicate]

How can I write :hover and :visited condition for a:before?
I'm trying a:before:hover, but it's not working.
This depends on what you're actually trying to do.
If you simply wish to apply styles to a :before pseudo-element when the a element matches a pseudo-class, you need to write a:hover:before or a:visited:before instead. Notice the pseudo-element comes after the pseudo-class (and in fact, at the very end of the entire selector). Notice also that they are two different things; calling them both "pseudo-selectors" is going to confuse you once you run into syntax problems such as this one.
If you're writing CSS3, you can denote a pseudo-element with double colons to make this distinction clearer. Hence, a:hover::before and a:visited::before. But if you're developing for legacy browsers such as IE8 and older, then you can get away with using single colons just fine.
This specific order of pseudo-classes and pseudo-elements is stated in the spec:
One pseudo-element may be appended to the last sequence of simple selectors in a selector.
A sequence of simple selectors is a chain of simple selectors that are not separated by a combinator. It always begins with a type selector or a universal selector. No other type selector or universal selector is allowed in the sequence.
A simple selector is either a type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class.
A pseudo-class is a simple selector. A pseudo-element, however, is not, even though it resembles a simple selector.
However, for user-action pseudo-classes such as :hover1, if you need this effect to apply only when the user interacts with the pseudo-element itself but not the a element, then this is not possible other than through some obscure layout-dependent workaround. As implied by the text, standard CSS pseudo-elements cannot currently have pseudo-classes. In that case, you will need to apply :hover to an actual child element instead of a pseudo-element.
1 Of course, this does not apply to link pseudo-classes such as :visited as in the question, since pseudo-elements aren't links.
Write a:hover::before instead of a::before:hover: example.
To change a menu link's text on mouseover (different language text on hover), here is the
jsfiddle example
HTML:
<a align="center" href="#"><span>kannada</span></a>
CSS:
span {
font-size: 12px;
}
a {
color: green;
}
a:hover span {
display: none;
}
a:hover:before {
color: red;
font-size: 24px;
content: "ಕನ್ನಡ";
}
Try to use .card-listing:hover::after, hover, and after using ::. It will work.
Or you can set pointer-events:none to your a element and pointer-event:all to your a:before element, and then add hover CSS to a element:
a{
pointer-events: none;
}
a:before{
pointer-events: all
}
a:hover:before{
background: blue;
}
BoltClock's answer is correct. The only thing I want to append is that if you want to only select the pseudo element, put in a span.
For example:
<li><span data-icon='u'></span> List Element </li>
instead of:
<li> data-icon='u' List Element</li>
This way you can simply say
ul [data-icon]:hover::before {color: #f7f7f7;}
which will only highlight the pseudo element, not the entire li element.
You can also restrict your action to just one class using the right pointed bracket (">"), as I have done in this code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
span {
font-size: 12px;
}
a {
color: green;
}
.test1>a:hover span {
display: none;
}
.test1>a:hover:before {
color: red;
content: "Apple";
}
</style>
</head>
<body>
<div class="test1">
<span>Google</span>
</div>
<div class="test2">
<span>Apple</span>
</div>
</body>
</html>
Note: The hover:before switch works only on the .test1 class

Different behavior for pseudo-class with space and without space

This issue is related to CSS pseudo-class. I refer to :last-child just for example, I suppose it happens to all other pseudo-class too.
Given I have following simple HTML:
<body>
<p>Paragraph1</p>
<p>Paragraph2</p>
</body>
I add following CSS:
body:last-child{
color:red;
}
<body>
<p>Paragraph1</p>
<p>Paragraph2</p>
</body>
Without space both paragraphs will be marked as red
When I will set space between .body and :last-child, only second paragraph will be marked as red - that happens in Google Chrome, I see snippet tool doesn't mark any paragraph with red.
body: last-child{
color:red;
}
<body>
<p>Paragraph1</p>
<p>Paragraph2</p>
</body>
Question: Could anyone help me understand why this happens? Maybe anything to read more on behaviour with space and without space for pseudo-class?
It's last paragraph not last body.
So, just do this:
body p:last-child{
color: red;
}
Space separates the next level of elements for css selector to work.
pseudo-element should always work without Space in between of element and colon .eg
body p:last-child{ color:red; }
1. Without spacing
body:last-child {
color: red;
}
<body>
<p>Paragraph1</p>
<p>Paragraph2</p>
</body>
In the above code, all the p elements are red because color: red is applied to the body and is applied to the child elements as well. body:last-child, here :last-child is w.r.t to the parent and does not mean last child of body element.
2. With spacing
body: last-child{
color:red;
}
The above is invalid syntax and does not apply styling. You can validate your CSS: W3C CSS Validator
3. Solution:
body p:last-child { /* Select the paragraph which is last inside body */
color: red;
}
Avoid using this in SO snippets as the child selectors will be difficult to style. <link> and <script> is added/appended to the markup and disrupts the child selector.
With body:last-child, you target the last body (and there is only one). So everything within the body will be colored red.
The body: last-child doesn't work, because it is invalid.
What you are looking for is body p:last-child.

I'm trying to figure out why the first class in my css is taking precedence

I'm trying to figure out why the first class in my css is taking precedence, I thought if you call two classes, the last class gets the call.
Here is my example:
Test CSS Precedenceenter code here
<style>
/* Scenario 1 */
.blue { color:blue; };`enter code here`
.red { color:red; };
</style>
</head>
<body>
<div class="red blue">Red Blue</div> <!-- CSS Specifity (0,0,2,1) -->
<div class="blue red">Blue Red</div> <!-- CSS Specifity (0,0,2,1) -->
</body>
</html>
The CSS is invalid, it should look something like this:
.blue { color:blue; }
.red { color:red; }
Take a look at CSS syntax documentation. The semi-colon ; shouldn't appear outside of the curly brackets. Because of this error, the styling from .red wasn't being applied to any elements at all.
Aside from that; a stylesheet is cascade. It is read from top to bottom, therefore if an element contains both classes (regardless of order), .red will still overwrite .blue because it appears later in the stylesheet. (example here)
As Josh said, the later specified attribute is the one that will have greater importance. Have a read through this article on CSS specificity if you'd like further clarification.
http://coding.smashingmagazine.com/2007/07/27/css-specificity-things-you-should-know/

Can I use css3 not selector with pseudo class?

<style type="text/css">
p:not(p:first-letter)
{
color:#000;
}
</style>
<p style="color:Blue">
test test
</p>
It's not working as expected as all the letters of paragraph should be in black except first.
No.
the first-letter pseudo-element is not part of the collection returned by the p selector. You can't exclude it then.
Why don't you just use :
<style type="text/css">
p
{
color:#000;
}
p:first-letter{
color:blue;
}
</style>
<p style="color:Blue">
test test
</p>
By the way, this is not a good practice at all. You should use a class on your p element and style via css. You don't need to generate css dynamically for that.
<style type="text/css">
p.test
{
color:#000;
}
p.test:first-letter{
color:blue;
}
</style>
<p class="test">
test test
</p>
The negation CSS pseudo-class, :not(X), is a functional notation
taking a simple selector X as an argument. It matches an element that
is not represented by the argument. X must not contain another
negation selector, or any pseudo-elements.
That means you cant use ::first-letter as an argument of :not(), because it's a pseudo-element.
Try the other way around:
http://jsfiddle.net/YET8v/1/
HTML:
<p>Test test</p>
CSS:
p {
color: #000;
}
p::first-letter {
color: blue;
}
The css selector not only takes simple selectors as parameter.
A simple selector is: a single element, attribute selector, class, id or pseude-class.
Examples of simple selectors:
body
*
[value="foo"]
.foo
#foo
:hover

How can I write a ':hover' condition for 'a:before' and 'a:after'?

How can I write :hover and :visited condition for a:before?
I'm trying a:before:hover, but it's not working.
This depends on what you're actually trying to do.
If you simply wish to apply styles to a :before pseudo-element when the a element matches a pseudo-class, you need to write a:hover:before or a:visited:before instead. Notice the pseudo-element comes after the pseudo-class (and in fact, at the very end of the entire selector). Notice also that they are two different things; calling them both "pseudo-selectors" is going to confuse you once you run into syntax problems such as this one.
If you're writing CSS3, you can denote a pseudo-element with double colons to make this distinction clearer. Hence, a:hover::before and a:visited::before. But if you're developing for legacy browsers such as IE8 and older, then you can get away with using single colons just fine.
This specific order of pseudo-classes and pseudo-elements is stated in the spec:
One pseudo-element may be appended to the last sequence of simple selectors in a selector.
A sequence of simple selectors is a chain of simple selectors that are not separated by a combinator. It always begins with a type selector or a universal selector. No other type selector or universal selector is allowed in the sequence.
A simple selector is either a type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class.
A pseudo-class is a simple selector. A pseudo-element, however, is not, even though it resembles a simple selector.
However, for user-action pseudo-classes such as :hover1, if you need this effect to apply only when the user interacts with the pseudo-element itself but not the a element, then this is not possible other than through some obscure layout-dependent workaround. As implied by the text, standard CSS pseudo-elements cannot currently have pseudo-classes. In that case, you will need to apply :hover to an actual child element instead of a pseudo-element.
1 Of course, this does not apply to link pseudo-classes such as :visited as in the question, since pseudo-elements aren't links.
Write a:hover::before instead of a::before:hover: example.
To change a menu link's text on mouseover (different language text on hover), here is the
jsfiddle example
HTML:
<a align="center" href="#"><span>kannada</span></a>
CSS:
span {
font-size: 12px;
}
a {
color: green;
}
a:hover span {
display: none;
}
a:hover:before {
color: red;
font-size: 24px;
content: "ಕನ್ನಡ";
}
Try to use .card-listing:hover::after, hover, and after using ::. It will work.
Or you can set pointer-events:none to your a element and pointer-event:all to your a:before element, and then add hover CSS to a element:
a{
pointer-events: none;
}
a:before{
pointer-events: all
}
a:hover:before{
background: blue;
}
BoltClock's answer is correct. The only thing I want to append is that if you want to only select the pseudo element, put in a span.
For example:
<li><span data-icon='u'></span> List Element </li>
instead of:
<li> data-icon='u' List Element</li>
This way you can simply say
ul [data-icon]:hover::before {color: #f7f7f7;}
which will only highlight the pseudo element, not the entire li element.
You can also restrict your action to just one class using the right pointed bracket (">"), as I have done in this code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
span {
font-size: 12px;
}
a {
color: green;
}
.test1>a:hover span {
display: none;
}
.test1>a:hover:before {
color: red;
content: "Apple";
}
</style>
</head>
<body>
<div class="test1">
<span>Google</span>
</div>
<div class="test2">
<span>Apple</span>
</div>
</body>
</html>
Note: The hover:before switch works only on the .test1 class

Resources