Matthew Matthew - 5 months ago 14
CSS Question

CSS/JS: Targeting :nth-child consistant across 2 parent elements?

Let's say we have a setup like this:



.col:nth-child(2n+1) {
background: red;
}

/* Style the div's for testing */
div.row {
width: 100%;
border: 1px solid blue;
}
div.col {
padding: 12px 0;
width: 100%;
}

<div class="row"><!-- The .col's in this row are dynamically generated -->
<div class="col 1"></div>
<div class="col 2"></div>
<div class="col 3"></div>
<div class="col 4"></div>
<div class="col 5"></div>
</div>
<div class="row">
<div class="col 1"></div>
<div class="col 2"></div>
<div class="col 3"></div>
<div class="col 4"></div>
</div>





Here's a working Fiddle: https://jsfiddle.net/1L4rodh4/

Now... the
Nth selector
is working as it should. The problem is that I want to get the elements styled consistently. so that it appears to be seamless between the 2
.row
's. The
.col
's in the first
.row
are dynamically generated and could end up being
even
or
odd
.

Please ask me for clarification if I wasn't clear. I couldn't find any information about this elsewhere. This is something that seems so simple, yet it seems to be impossible.

Is there a better way of doing this, or am I stuck?




I understand I could use JS to get the number of "col"'s in the first "row" and change the selector in the second row. That just seems way too hack-ish for this though.

EDIT: I will accept a JS solution.




The following is a working example of how this can be done with a simple plain JS script, based on the code in the selected answer below.



var cols = document.querySelectorAll('.table.js-fix .tr');
for (var i = 0; i < cols.length; i++) {
cols[i].classList.add(i % 2 == 0 ? 'even' : 'odd');
}

.table.js-fix .tr:nth-child(2n + 1), /* :nth-child fallback */
.table.js-fix .tr.even {
background: red;
}
.table.js-fix .tr.odd {
background: #fff;
}

/* Style for testing */
.table {
width: 100%;
border: 1px solid blue;
}
.tr {
padding: 12px 0;
width: 100%;
}

<div class="row"><!-- The .tr in this row is just used as a thead -->
<div class="col">
<div class="table">
<div class="tr">Section Title</div>
</div>
</div>
</div>
<div class="row"><!-- The .tr's in this row are dynamically generated -->
<div class="col">
<div class="table js-fix">
<div class="tr"></div>
<div class="tr"></div>
<div class="tr"></div>
</div>
</div>
</div>
<div class="row"><!-- There will always be 5 .tr's in this row -->
<div class="col">
<div class="table js-fix">
<div class="tr"></div>
<div class="tr"></div>
<div class="tr"></div>
<div class="tr"></div>
<div class="tr"></div>
</div>
</div>
</div>





JSFiddle with the above example: https://jsfiddle.net/n12h70j6/

Answer

You can do that with CSS. See this or this.

.col:first-child:nth-last-child(even) ~ .col:nth-child(2n + 1),
.col:first-child:nth-last-child(even){
  background-color: red;
}

.col:first-child:nth-last-child(odd) ~ .col:nth-child(2n + 2){
  background-color: red;
}

This checks if the number of children are even or odd and styles them appropriately.

Update: Inspite of what it might look like. This will not work for cases when a parent with odd number of children directly follows another parent with odd number of children (which was the whole point). However I am leaving this here for someone else to get ideas running in their heads.

Since it is still an answer, CSS alone cannot do this, so one must resort to javascript / jQuery.

This could be one way to do this with plain JS

var cols = document.querySelectorAll('.col');
for(var i = 0; i < cols.length; i++)
    cols[i].classList.add(i % 2 == 0 ? 'some-class' : 'alternate-class');
Comments