Partial grouping of a CSS selector - css

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.

Related

Find first CSS class on page

I have a page full of elements. I simply just want to match the first element in my CSS selector.
I have tried sibling selector, first-child and first-of-type but they all only work in a structure where there are siblings. In my case I have different depths which makes it harder.
.match ~ .match {
background:red;
}
.match:first-child {
background: green;
}
.match:first-of-type {
background: yellow;
}
<div>
<ul>
<li>List item</li>
</ul>
<div>
<div class="match">Match - First match should be red</div>
</div>
<div class="match">Match</div>
<button></button>
<div>
<div>
<div class="match">Match</div>
</div>
</div>
</div>
It should find the first element with the class .match.
I will not accept answers like div > div > .match because then it does not find the element because we tell it where to look.
That is not possible with pure CSS. If the HTML is static, you can add an ID or another class, as Snake_py suggested. If you're okay with using a script, the document.querySelector method returns the first match of the selector, so you could do something like this: (see snippet)
document.querySelector('.match').classList.add('match-active')
.match-active {
background:red;
}
<div>
<ul>
<li>List item</li>
</ul>
<div>
<div class="match">Match - First match should be red</div>
</div>
<div class="match">Match</div>
<button></button>
<div>
<div>
<div class="match">Match</div>
</div>
</div>
</div>

Css :not pseudo class is not taking effect

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;
}

change other element when mouse over in CSS

i want to change other element outside current element level in CSS3. i have tried to use plus symbol but still not working.
<div id="a">
<div id="a_1">
<ul>
<li>test1</li>
<li>test2</li>
</ul>
</div>
</div>
<div id="b">
</div>
i want to change #b background-color i try this but not still work
a ul li:hover #b{
background-color:blue;
}
and also tried this but not working too
a ul li:hover + #b{
background-color:blue;
}
You must use JavaScript or JQuery for that.

Display first occurrence after a class that is nested

I want the first class .tab immediately following the class .tab-wrapper to be visible, the rest should not be displayed
<ul class="tabs">
<li>1</li>
<li>2</li>
</ul>
<div class="tab-wrapper">
<div class="tab">VISIBLE</div>
<div class="tab"></div>
<div class="tab">
<ul class="tabs">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<div class="tab-wrapper">
<div class="tab">VISIBLE</div>
<div class="tab"></div>
<div class="tab"></div>
</div>
</div>
</div>
This is my css. For some reason the first .tab of the second .tab-wrapper does not display...
How do i fix it?
Thanks
.tab-wrapper .tab {display: none;}
.tab-wrapper .tab:first-child {display: block;}
This is working, although when I copied/pasted your code it did not? (Of course, copying your CSS into the fiddle now appears to work. If you're trying to get the second VISIBLE to display, you're out of luck unless you modify your methodology.)
.tab-wrapper .tab {
display: none;
}
.tab-wrapper .tab:first-child {
display: block;
}
http://jsfiddle.net/zW7dz/
Also, as #barmar points out, your second inner/inner .tab can't be shown because it's parent (.tab) is going to get the display: none. You can't see it if it's parent is not visible.

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