CSS sibling selector on class names? - css

<div class="parent">
<div class="firstChild"></div>
<div class="secondChild"></div>
<div class="thirdChild"></div>
<div class="fourthChild"></div>
<div>
I am trying to style fourthChildbased on if secondChild exists under parent
I thought the below would work but Chrome says no. I dont want to use nth child because the DOM could change based on our program, the below seems very flexible but I'm doing something wrong.
.parent .secondchild ~ .fourthchild
{
css stuff
}

It's the correct solution, you just wrongly named your classes in the CSS, you forgot the caps.
.parent .secondChild ~ .fourthChild
http://jsfiddle.net/LeBen/Y6QDr/

It's case sensitive!
Do this:
.parent .secondChild ~ .fourthChild

Related

Why does nth-of-type not consider the class? [duplicate]

Is it possible to use the CSS3 selector :first-of-type to select the first element with a given class name? I haven't been successful with my test so I'm thinking it's not?
The Code (http://jsfiddle.net/YWY4L/):
p:first-of-type {color:blue}
p.myclass1:first-of-type {color:red}
.myclass2:first-of-type {color:green}
<div>
<div>This text should appear as normal</div>
<p>This text should be blue.</p>
<p class="myclass1">This text should appear red.</p>
<p class="myclass2">This text should appear green.</p>
</div>
No, it's not possible using just one selector. The :first-of-type pseudo-class selects the first element of its type (div, p, etc). Using a class selector (or a type selector) with that pseudo-class means to select an element if it has the given class (or is of the given type) and is the first of its type among its siblings.
Unfortunately, CSS doesn't provide a :first-of-class selector that only chooses the first occurrence of a class. As a workaround, you can use something like this:
.myclass1 { color: red; }
.myclass1 ~ .myclass1 { color: /* default, or inherited from parent div */; }
Explanations and illustrations for the workaround are given here and here.
The draft CSS Selectors Level 4 proposes to add an of <other-selector> grammar within the :nth-child selector. This would allow you to pick out the nth child matching a given other selector:
:nth-child(1 of p.myclass)
Previous drafts used a new pseudo-class, :nth-match(), so you may see that syntax in some discussions of the feature:
:nth-match(1 of p.myclass)
This has now been implemented in WebKit, and is thus available in Safari, but that appears to be the only browser that supports it. There are tickets filed for implementing it Blink (Chrome), Gecko (Firefox), and a request to implement it in Edge, but no apparent progress on any of these.
This it not possible to use the CSS3 selector :first-of-type to select the first element with a given class name.
However, if the targeted element has a previous element sibling, you can combine the negation CSS pseudo-class and the adjacent sibling selectors to match an element that doesn't immediately have a previous element with the same class name :
:not(.myclass1) + .myclass1
Full working code example:
p:first-of-type {color:blue}
p:not(.myclass1) + .myclass1 { color: red }
p:not(.myclass2) + .myclass2 { color: green }
<div>
<div>This text should appear as normal</div>
<p>This text should be blue.</p>
<p class="myclass1">This text should appear red.</p>
<p class="myclass2">This text should appear green.</p>
</div>
I found a solution for your reference. from some group divs select from group of two same class divs the first one
p[class*="myclass"]:not(:last-of-type) {color:red}
p[class*="myclass"]:last-of-type {color:green}
BTW, I don't know why :last-of-type works, but :first-of-type does not work.
My experiments on jsfiddle... https://jsfiddle.net/aspanoz/m1sg4496/
This is an old thread, but I'm responding because it still appears high in the list of search results. Now that the future has arrived, you can use the :nth-child pseudo-selector.
p:nth-child(1) { color: blue; }
p.myclass1:nth-child(1) { color: red; }
p.myclass2:nth-child(1) { color: green; }
The :nth-child pseudo-selector is powerful - the parentheses accept formulas as well as numbers.
More here: https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-child
You can do this by selecting every element of the class that is the sibling of the same class and inverting it, which will select pretty much every element on the page, so then you have to select by the class again.
eg:
<style>
:not(.bar ~ .bar).bar {
color: red;
}
<div>
<div class="foo"></div>
<div class="bar"></div> <!-- Only this will be selected -->
<div class="foo"></div>
<div class="bar"></div>
<div class="foo"></div>
<div class="bar"></div>
</div>
As a fallback solution, you could wrap your classes in a parent element like this:
<div>
<div>This text should appear as normal</div>
<p>This text should be blue.</p>
<div>
<!-- first-child / first-of-type starts from here -->
<p class="myclass1">This text should appear red.</p>
<p class="myclass2">This text should appear green.</p>
</div>
</div>
Not sure how to explain this but I ran into something similar today.
Not being able to set .user:first-of-type{} while .user:last-of-type{} worked fine.
This was fixed after I wrapped them inside a div without any class or styling:
https://codepen.io/adrianTNT/pen/WgEpbE
<style>
.user{
display:block;
background-color:#FFCC00;
}
.user:first-of-type{
background-color:#FF0000;
}
</style>
<p>Not working while this P additional tag exists</p>
<p class="user">A</p>
<p class="user">B</p>
<p class="user">C</p>
<p>Working while inside a div:</p>
<div>
<p class="user">A</p>
<p class="user">B</p>
<p class="user">C</p>
</div>
I found something that works
If you have a bigger class which contains something like grid, all of elements of your another class
You can do like that
div.col-md-4:nth-child(1).myclass{
border: 1px solid #000;
}
Simply :first works for me, why isn't this mentioned yet?

Target a div only when another div in the dom has a class of X

Is there a way to target div.music only when the div a few more up has a class of success? The success class gets added dynamically so I only want to target div.music when .success exists in the DOM.
For example, I know that if .music was right below .success, I can do something like this:
.success + .music { styles here } using the adjacent selector. However, what if the two divs aren't adjacent to each other like this?
<div>
<div class="success"></div>
<div class="blah"></div>
<div class="blah"></div>
<div class="blah"></div>
<div class="music"></div>
</div>
Yes, use the general sibling selector: ~
.success ~ .music {
color:red;
}
jsFiddle example
The ~ combinator separates two selectors and matches the second
element only if it is preceded by the first, and both share a common
parent.

Conditional CSS: if sibling's child div is present, then

In the html fragment below, I want the "main" div to have a background image only if "menu" div is not present in the markup. Is this possible?
<div class="header">
<div class="siteTitle">site title</div>
<div class="tagline">site tagline</div>
<div class='menu'></div>
</div>
<div class="main"></div>
http://www.w3.org/TR/css3-selectors/
E + F Matches any F element immediately preceded by a sibling element E.
E:not(s) an E element that does not match simple selector s
edit :not uses a simple selector, so unfortunately you can't use it to filter by properties of children, only attributes of the element.
A simple selector is either a type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class.
You could however put a .empty class on the menu and still use it.
.header .menu:not(.empty) + .main {
background:pink;
}
This solution is the best of both worlds, javascript but using css as per normal.
javascript:
if ($('.menu').length == 0){
$('body').addClass('no_menu');
}
css :
body.no_menu .main{
background:pink;
}
The only pure css solution i see is only possible if you rearrange your html like so:
<div class="header">
<div class="siteTitle">site title</div>
<div class="tagline">site tagline</div>
</div>
<div class="menu"></div>
<div class="main"></div>
then you can use this css to only apply a property):
.menu { background: none }
.menu ~ .main{ background: url() } /* or .menu + .main if they are guaranteed to be adjacent to each other on the code */
in this example, you can see it at work: http://jsfiddle.net/tYhxr/
(test it by deleting the menu div and running it again)
check Keyo's asnwer for a link about how selectors work.
If you can't change the html, the javascript is the way to go.
I hope this helps.
You could add a second class to your main <div> that only serves to add the background you want. Then when you create the markup, you just add the second class specifier to the <div> if you need it, or omit it if you don't.
div.main {
//main stuff
}
div.mainbg {
background: *background-specifications*;
}
When your menu div is present, you use this:
<div class="main mainbg">
And when it's missing, you stick with:
<div class="main">

Tricky CSS conditional sibling > child selector > Can this be done?

In the markup below, I'm looking for a way (perhaps using css selector's) to style the content div differently depending on the presence of menu? Menu may or may not be present in that location in the markup and if it is there, I need to add some top margin to content.
I believe sibling and descendent selector rules might not go this far...
"When menu is present as a child of header set the top margin of content (whose parent is a sibling of header) to 100 pixels. Otherwise, set it to zero"
<div class="header">
<div class="sitetitle">site title</div>
<div class="tagline">tagline</div>
<div class="menu">menu</div>
</div>
<div class="main">
<div class="content">content goes here</div>
</div>
If css allowed groupings, I would do it this way...
(.header ~ .menu) + (.main > .content) {margin-top:100px;}
Not possible in your markup.
CSS selectors can only look at the ancestor and at the sibling axes. You cannot look inside ("what children do I have") - only upwards ("what are my parents") and sideways ("what's next to me").
Examples. This:
div.header div.menu
refers to any <div class="menu"> one of whose ancestors is a <div class="header">.
This:
div.header > div.menu
refers to any <div class="menu"> whose direct ancestor (i.e. "parent") is a <div class="header">.
This:
div.header ~ div.menu
refers to any <div class="menu"> that has a <div class="header"> among its preceding siblings, i.e. they have the same parent and occur one after another, but not necessarily adjacent to each other (that's "looking sideways").
This:
div.header + div.menu
refers to any <div class="menu"> whose direct preceding sibling is a <div class="header">.
There are no other traversing selectors in CSS (this statement refers to CSS2) and certainly there are no conditionals.
You could use jQuery:
​$('.header:has(.menu) + .main > .content')​.css('margin-top', '100px');​​​​​​​​​​​
Unfortunately the :has() selector didn't find its way into css3.
But why don't you simply apply a margin-bottom to div.menu?
You could possibly use some javascript to detect that. Check if menu is under header at load, and if it is, then set the margin-top of content to 100px
I used this CSS code in a conditional formatting.
Format index by counting from the end.
#stk-service-account-menu ul li:nth-last-child(1):before {

CSS Change background parent of element

I have some problem that i want to change it with css
<div class="a">
<div class="b">
<span></span>
</div>
<div class="c">
<span></span>
</div>
<div class="d">
<span class="e"></span>
</div>
</div>
I want to change background of div.b and div.c by using span.e
Please help me.
Thanks
The following answer assumes you are asking how to use span.e as part of a selector to change the rules for div.b and div.c. For example:
span.e:parent:prevAll.b { background:red } // concept-code, doesn't actually work
You can't do that with CSS alone, you would need to use something like jQuery (javascript) to handle this for you. With CSS, you can reference children from parents, but not parents from children. Or in this case uncles from nephews...
At current, CSS cannot go up the chain (child to parent) only down the chain (parent to child). You could probably use jQuery to do what you want here, but you should probably rewrite the HTML so its not difficult.
You can't do that with CSS, you'd need something like jQuery. It's difficult to know exactly what to suggest since it's unclear how you want the system to work, but this should help:
$('.e').parents('div').eq(0).addClass('red');
You would already have a class in your CSS: .red { background-color: red; } (you might want to name it better though).

Resources