Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS select: how to count and select child of a specific class only?

Given the HTML where all items are at the same level such:

<div class="h2">Title: Colors</div>
 <div class="pair">Hello world (1)</div>
 <div class="pair">Hello world (2)</div>
 <div class="pair">Hello world (3)</div>
 <div class="pair">Hello world (4)</div>
 <div class="pair">Hello world (5)</div>
 <div class="pair">Hello world (6)</div>

<div class="h2">Title: Units</div>
 <div class="pair">Hello world (1)</div>
 <div class="pair">Hello world (2)</div>
 <div class="pair">Hello world (3)</div>
 <div class="pair">Hello world (4)</div>
 <div class="pair">Hello world (5)</div>
 <div class="pair">Hello world (6)</div>

How do I select the n+3 and n+4 .pair elements starting from the previous .h2 element ?

So the 1&2 are white, 3&4 are pink, 5&6 are white, etc.

I tried .pair:nth-child(4n+3), .pair:nth-child(4n+4) { background: #FFAAAA; } but it counts the child of the body where the h2 are also children and thus breaks my balance.

http://jsfiddle.net/zPYcy/2/


Edit: no pure CSS selector was found to select adjacent items following a pattern such as .class (n+3). Alternatively, an infinite series of CSS selectors such div + .class + .class + .class ...; wrapping in a div together with :nth-child(n+3) or :nth-of-type(n+3); or JS is needed. You know another hack ? Sharing welcome !

like image 939
Hugolpz Avatar asked May 14 '13 22:05

Hugolpz


3 Answers

This is a solution combining sibling , nth-child and nth-last-child selector.

Each of your divs with class h2 should also use an extra class that I will call "colors" and "units" like so:

<div class="h2 colors">Title: Colors</div>
...
<div class="h2 units">Title: Colors</div>
...

We apply for all children that presents a preceding sibling with classes h2 and colors the following rule which will paint the pink divs

.h2.colors ~ .pair:nth-child(4n+4), .h2.colors ~ .pair:nth-child(4n+5) { 
    background: #FFAAAA; 
}

Of course this will also paint those divs below the div of classes h2 and units. We don`t want that to happen. So now we apply the following two rules, selecting in inverse order up to h2 units.

.h2.units ~ .pair:nth-last-child(4n+3), .h2.units ~ .pair:nth-last-child(4n+4) { 
    background: #FFAAAA; 
}

Be aware that now we must also apply the white background to fix the extra divs painted by our first rule So...

 .h2.units ~ .pair:nth-last-child(4n+1), .h2.units ~ .pair:nth-last-child(4n+2) { 
        background: #ffffff; 
    }

Only thing to take care is the odd or even number of divs in the last group when we are using the nth-last-child selector.

And there you are!

Here is the fiddle to play with

like image 81
Fico Avatar answered Sep 22 '22 21:09

Fico


If we want only the 3rd and 4th .pair after each .h2, then this will work:

.h2 + .pair + .pair + .pair,
.h2 + .pair + .pair + .pair + .pair { background: #FFAAAA; }

If we want to continue to alternate by two even in a longer list, we will need another solution.


EDIT: Since we do want a scalable solution, if we can change the markup slightly by wrapping each block of .pair items with another class:

<div class="h2 colors">Title: Colors</div>
<div class="pairList">
    <div class="pair">Hello world</div>
    <div class="pair">Hello world</div>
    <div class="pair">Hello world</div>
    <div class="pair">Hello world</div>
    ...
</div>

Then we can write a rule that will scale for any amount of items like:

.pairList .pair:nth-of-type(4n+3), 
.pairList .pair:nth-of-type(4n+4) { 
    background: #FFAAAA; 
}

Here is a FIDDLE

like image 42
Dan Avatar answered Sep 22 '22 21:09

Dan


Out of boredom and curiosity I've written a function to do this. In the case that you are stuck with the html as is and you have extended rows like this, my plugin could be useful to you.

Copy the function from my jsFiddle and use like so:

var pair1 = findCousin('h2', 'pair', '4n+2');
var pair2 = findCousin('h2', 'pair', '4n+3');
var s = pair1.add(pair2);

You can change h2 and pair two different class names, or use different patterns as long as it has #n in it, and optionally +# just like the css nth child selector. Adding false as a fourth argument...

findCousin('list-title', 'list-item', '3n', false);

...will select everything after the first list-title in the given pattern, rather than after each list-item.... if that makes any sense.

I believe sh0ber has written a more practical solution, but this has been fun to make and I might as well share.

http://jsfiddle.net/REU33/6/

like image 21
jamil Avatar answered Sep 25 '22 21:09

jamil