Css :not pseudo class is not taking effect - css

I want to use the :not pseudo class as an exception where the css should apply to everything except any element with a certain class including all its children elements.
But in my example, the :not selector is affecting everything, but only should affect the class inside the :not selector. I'm using chrome browser.
fiddle
SCSS:
.ql-editor :not(.not-ql-editor){
ul > li {
background:blue;
}
}
HTML:
<div class="ql-editor">
<ul>
<li>hello</li>
<li>hello</li>
<li>hello</li>
</ul>
<div class="not-ql-editor">
<ul>
<li>hello</li>
<li>hello</li>
<li>hello</li>
</ul>
</div>
</div>
I would have expected the top <ul><li> to have blue background, while the lower <ul><li> would not have a background because it has the .not-ql-editor class, but something seems wrong since no li elements get the background.
Update:
After the answer by Johannes I learned that the upper ul needs to be wrapped inside some element because the :not(.not-ql-editor) represents an element even if it doesn't match the selector.
But then I noticed that the "not-ql-editor" element has to be directly underneath the "ql-editor" element. My aim was to target a class at any level beneath "ql-editor".
Normally when you but a space between two selectors, the second selector should target elements at any level beneath the first one. Is this not the case with the :not selector?
update2:
Here is a modified version of the fiddle:
fiddle2
If the html looks like this (with the same css):
<div class="ql-editor">
<div>
<div class="not-ql-editor">
<ul>
<li>hello</li>
<li>hello</li>
<li>hello</li>
</ul>
</div>
</div>
</div>
The li's become blue. Despite the css: .ql-editor :not(.not-ql-editor)

The problem in your code is that the first list is on a different "descendant level" than the second list: Your CSS selector is valid only for li elements inside a ul which is child of an element that does not have the .not-ql-editor which again is child of an element that has the .ql-editor class.
For this to work you need another div (or other) wrapper around your first ul:
.ql-editor :not(.not-ql-editor) ul>li {
background: blue;
}
<div class="ql-editor">
<div>
<ul>
<li>hello></li>
<li>hello</li>
<li>hello</li>
</ul>
</div>
<div class="not-ql-editor">
<ul>
<li>hello</li>
<li>hello</li>
<li>hello</li>
</ul>
</div>
</div>
ADDITION after comments and edit of question:
In the first code example you posted, your ul elements were on different descendant levels from the .ql-editor DIV element: The first ul was a directchild, the second one a grandchild, with the .not-ql-editor DIV as a wrapper between .ql-editor and the ul. My answer was directed at this situation, and it worked.
In the second code example you posted, you added another level: A DIV without any class in between the .ql-editor DIV and the .not-ql-editor DIV. This changes things. In the fiddle you added, the .not-ql-editor DIV is the direct parent of the ul. So you need to use that relationship to define a CSS rule that only applies if the ul is a direct child of a DIV that does not have the .not-ql-editor class.
in plain CSS that rule would be as follows:
.ql-editor *:not(.not-ql-editor) > ul > li {
background: blue;
}
Here's your second code example combined with that CSS rule in a snippet, The background does * not* become blue:
.ql-editor *:not(.not-ql-editor) > ul > li {
background: blue;
}
<div class="ql-editor">
<div>
<div class="not-ql-editor">
<ul>
<li>hello</li>
<li>hello</li>
<li>hello</li>
</ul>
</div>
</div>
</div>
And here's your second fiddle with this CSS applied as SCSS: https://jsfiddle.net/e7d0h4yc/

You can do this with the original HTML you had. Since the top ul element and the div.not-ql-editor element are siblings, you can just attach the not rule to a wildcard element, and instead of targeting ul > li just target li
.ql-editor>*:not(.not-ql-editor) li {
background: blue;
}
<div class="ql-editor">
<ul>
<li>hello</li>
<li>hello</li>
<li>hello</li>
</ul>
<div class="not-ql-editor">
<ul>
<li>hello</li>
<li>hello</li>
<li>hello</li>
</ul>
</div>
</div>

.ql-editor :not(.not-ql-editor){
ul > li {
background:blue;
}
}
Correct this to remove the space between ql-editor and :not
.ql-editor div :not(.not-ql-editor){
background:blue;
}

Related

Prevent CSS inheritance to children of the selected element

I have a menu consisting of nested ULs and LIs, eg:
.wrapper > ul:first-child > li:last-child {
color: red;
}
<div class="wrapper">
<ul>
<li>Lorem</li>
<li>Ipsum</li>
<li>Dolar</li>
<li>Style me!
<ul>
<li>Lorem</li>
<li>Don't style me!</li>
</ul>
</li>
</ul>
</div>
I want to add a style to the last <li> of the first <ul>, but not have it's children (the nested <ul>) inherit it.
I have tried:
.wrapper > ul:first-child > li:last-child {/*styles*/}
but this still styles the last element.
Would anyone know how I can target just that 1 element (with just CSS)?
Some CSS properties are inherited and you can't prevent that.
Inheritance propagates property values from parent elements to their children.
Some properties are inherited properties, as defined in their
property definition table. This means that, unless the cascade results
in a value, the value will be determined by inheritance.
However, you can override that by selecting the children and restoring the desired value.
.wrapper > ul:first-child > li:last-child {
color: red;
}
.wrapper > ul:first-child > li:last-child > * {
color: initial;
}
<div class="wrapper">
<ul>
<li>Lorem</li>
<li>Ipsum</li>
<li>Dolar</li>
<li>Style me!
<ul>
<li>Lorem</li>
<li>Don't style me!</li>
</ul>
</li>
</ul>
</div>

CSS Select all Anchors inside LI, Inside UL without adding classes to each anchor

I have the Next.
<div data-role='navbar'>
<ul class='mainNAV'>
<li><a href='#home'>Principal</a></li>
<li><a href='#'>Yo 360</a></li>
<li><a href='#'>Mercado</a></li>
</ul>
</div>
So in CSS.. without adding a CLASS inside each LI or ANCHOR element.
How can i select all the Anchors inside the UL with the class 'mainNAV'?
So i can change font size, colors, etc, to all items..
Thanks!
You can use an attribute selector to only target anchors:
.mainNAV a[href^="#"] {
color:red;
}
<div data-role='navbar'>
<ul class='mainNAV'>
<li><a href='#home'>Principal</a></li>
<li><a href='#'>Yo 360</a></li>
<li><a href='#'>Mercado</a></li>
<li><a href=''>Not anchor</a></li>
</ul>
</div>
ul.mainNAV a
Would be the most basic selector. You could also use:
div > ul.mainNAV > li > a
div > ul.mainNAV li a
div > ul.mainNAV a
div ul.mainNAV li a
... and probably a couple dozen more ways

Partial grouping of a CSS selector

I can't seem to find an answer to this so either it's not possible or i'm not wording my searches correctly - i'm hoping someone on here can help? :)
I have some HTML (UL in my example) who's grand-parent (div) occasionally has a sibling and occasionally doesn't. An example of this might be :
No Sibling Example
<section>
<div>
<div id="item">
<ul>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
</div>
</div>
</section>
Sibling Example
<section>
<div id="sibling1">xxx</div>
<div>
<div id="item">
<ul>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
</div>
</div>
<div id="sibling2">yyyy</div>
</section>
I want to select the UL element only when it's grandparent (div) has siblings.
I was going to use the preceding selector.. something like
section div div#item ~ ul
{
background: #ff0000;
}
but I cant seem to get it to work.
Any guidance greatly appreaciated!
section div~div div#item ul
{
background: #ff0000;
}
You need to select the parent div if it has a sibling. I'm not sure what your original selector was doing, but it was wrong.
Snippet with:
section div~div div#item ul
{
background: #ff0000;
}
<section>
<div id="sibling1">xxx</div>
<div>
<div id="item">
<ul>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
</div>
</div>
<div id="sibling2">yyyy</div>
</section>
Snippet without:
section div~div div#item ul
{
background: #ff0000;
}
<section>
<div>
<div id="item">
<ul>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
</div>
</div>
</section>
You can do this:
section>div:not(:only-child) ul{
background: red;
}
Here is a pen with two sections so you can see it works: http://codepen.io/vandervals/pen/qdqMvq
This has 2 advantages from the ~ method:
-It selects all ul from divs not only from one div.
-It is more readable.

Why last-child isn't working?

I got a problem for you to solve, as you know.
I ripped off all my hair trying to figure out why the heck last-child isn't working.
I tried to remove border-right with last-child but for some reasons, it didn't work out.
Here's is the link
Your selector is #countdown .num:last-child.
Your HTML is
<ul ID="countdown">
<li> <div ID="days" class="num">00</div> <div CLASS="text">days</div> </li>
<li> <div ID="hours" class="num">00</div> <div CLASS="text">hours</div> </li>
<li> <div ID="mins" class="num">00</div> <div CLASS="text">minutes</div> </li>
<li> <div ID="secs" class="num">00</div> <div CLASS="text">seconds</div> </li>
<div class="clear"></div>
</ul>
Think: is .num the last child of its parent? Answer: no.
Your selector should be more like #countdown > li:last-of-type .num, selecting .num inside the last li in #countdown.
Note that in this case last-of-type must be used rather than last-child because you've got that <div class="clear"></div>, which is invalid HTML (you can't have a div directly inside a ul).
The main reason why the last-child is not working because in your #countdown UL the last-child is <div class="clear"></div> not LI. So it's better to use last-of-type instead of last-child. Like this:
#countdown li:last-of-type .num,
#countdown li:last-of-type .text{
border:0;
}
Check this http://jsbin.com/apuhep/4/edit#html,live
Inside your ul element, there is a div element after the last li element. This is invalid markup and may have unpredictable effects. Moreover, it probably makes browsers treat the div element the last child of the ul element.

CSS Last-Child Selector - affecting all my DIVs?

I have the following
CSS
.streamBox {
font-size:12px;
background-color:#EDEFF4;
border-bottom:1px solid #E5EAF1;
margin-top:2px;
padding:5px 5px 4px;
}
.streamBox:last-child {
border: none;
}
HTML
<ul id="activityStream">
<li class="story">
<div class="streamBox nobkgcolor" id="">
Stuff
</div>
</li>
<li class="story">
<div class="streamBox nobkgcolor" id="">
Stuff
</div>
</li>
<li class="story">
<div class="streamBox nobkgcolor" id="">
Stuff
</div>
</li>
</ul>
I thought the last-child selector would make it so the last DIV doesn't hav ea border... But instead all DIVs now don't have borders? y?
Suggestions on how w CSS to make it so JUST the last div doesn't have the border?
Thanks,
For updated question:
Your selector needs a tweak, it should be:
li:last-child .streamBox {
border: none;
}
The <div class="streamBox"> is both the first and last child of its parent, so your current selector matches all of them, instead you want the <div> inside the last <li>, so use the :last-child on the <li>, you can test it here (I changed the border to black to make it more obvious).
For previous question:
It's because you're missing a quote on the class="" attribute, fix it like this:
<div class="box">blah blah</div>
<div class="box">blah blah</div>
<div class="box">blah blah</div>
<div class="box">blah blah</div>​​​​
It'll then work as intended, the first 3 having borders, you can test it here.

Resources