nth-child for every two table rows - css

I need to make every two rows of my table grey and I would prefer to use nth-child if possible.
I've messed around with Chris Coyier's nth-child tester but still can't get it.
I need the following formula:
1,2 - grey
3,4 - white
5,6 - grey
7,8 - white
9,10 - grey
and so on. I'd prefer not to put a class in the html as I'm sure that's going to be a suggestion from some. If there is a way to pull this off with nth-child, that's what I'm looking for.

Realize that you are doing groups of 4, then you can see that you can have every 4th element and every 4th element minus one being white, then every 4th element minus two, or every 4th element minus 3 being grey.
So, you'd use 4n and 4n-1, then 4n-2 and 4n-3:
div:nth-child(4n), div:nth-child(4n-1) {
background: red;
}
div:nth-child(4n-2), div:nth-child(4n-3) {
background: blue;
}
That code isn't precise to your case, I wrote it for a jsFiddle proof-of-concept.
NB disclaimer: Keep in mind that nth-child does not work in IE8. Typical issue, of course.

Here's what I'm using to right-align the first column of each table.
table td:nth-child(2n-1) {
align: right;
text-align: right;
}

#Eric's answer is exactly right - but if you want to easily extend this to groups of 3, 4, 5, etc, and you're using Sass, here's the code (if you want more groups, just increase $largestGroupSize):
.table-with-grouped-rows {
// generate styles for .groups-of-2, .groups-of-3, etc.
$largestGroupSize: 6;
#for $groupNumPerColor from 2 through $largestGroupSize{
$totalGroupNum: $groupNumPerColor * 2;
&.groups-of-#{$groupNumPerColor} {
$start: $totalGroupNum - 1;
$end: $groupNumPerColor;
#for $primaryBgIndex from $start through $end {
$nthString: #{$totalGroupNum}n - #{$primaryBgIndex};
> tbody > tr:nth-of-type(#{$nthString}) > td {
background-color: $white;
}
}
$start: $groupNumPerColor - 1;
$end: 0;
#for $alternateBgIndex from $start through $end {
$nthString: #{$totalGroupNum}n - #{$alternateBgIndex};
> tbody > tr:nth-of-type(#{$nthString}) > td {
background-color: $light-gray;
}
}
}
}
}
And then in your markup, on the <table> element, you'd simply add the classes table-with-grouped-rows and groups-of-{n}. For example, if you want a table with groups of 3, you'd write:
<table class="table-with-grouped-rows groups-of-3">
Boom.

Related

how to set background color on basis of css-counter of divs [duplicate]

This question already has an answer here:
cycling through a list of colors with sass
(1 answer)
Closed 7 years ago.
I have a set of data rows, each row shown as a tile of (label + value). I am wrapping them in a div.tilemap-tile
<div class="tilemap">
<div class="tilemap-tile" ng-repeat="x in data | orderBy: 'value'">
<div class="data-label">{{x.label}}</div>
<div class="data-value">{{x.value}}</div>
</div>
</div>
I would like to show this in a Nx3 or Nx4 styled grid such that - (a) the label for each row begins with a different color from a palette, and (b) the labels for subsequent tiles in the same row are successively darker.
I can get the grid visual by adjusting the tile properties
.tilemap-tile {
counter-reset: Z 0;
clear: both;
.tilemap-tile {
counter-increment: Z;
width: 33%;
display: table-cell;
float: left;
vertical-align: top;
height: 5em;
.data-label {
#include tile-bgcolor(red, counter(Z)); <<<<<<<<<<<<<<<<<<<<< PROBLEM
}
}
}
What I am struggling with is how to set the background of the data-label. I tried the following but it appears that counter can only be used within contents property. As a result, the computation below gives a sass error.
#mixin tile-bgcolor($basecolor, $p) {
$c: darken($basecolor, ($p % 3) * 5%); <<<<<<<<< $p is not numeric
&::after { content: "(debug, tile# " $p; }; <<<<< shows values 1..N
background: $c;
foobar: $p; <<< shows in browser as "counter(Z)"
}
Is there any other DRY way of keeping track of "div.tilemap-tile" count and using that in bg-color computations?
UPDATE
I don't know how to respond to "already has an answer" link but although helpful it is clearly not an answer. Please see my question again for the two specific requirements. Based on #cinnamon's comments, I don't think there is a pure-SASS/CSS answer.
#cimmanon points out that you cannot use counter() in SASS because it is a CSS function, not a SASS function. Your browser will understand it, but the SASS compiler just outputs it as a string. However, you can approximate what you need with SASS and nth-child. If you have a palette like:
// add as many colors as you want; colors will repeat
$palette: (#EBE998, #D1D6B5, #A1BEC6, #777FC0, #59546A);
Then, for each color output an nth-child rule. (I'm using a table as my markup but you get the idea).
$i : 1;
#each $color in $palette{
// select every [length of list]th table row, starting with first, second, etc
tr:nth-child(#{length($palette)}n + #{$i}){
background-color: $color;
}
$i: $i + 1;
}
The darkening along the rows is a little more of a hack...basically use a second element (in my case, the tds inside the rows but you can adjust to your markup), and use a progressively less-transparent black background color:
// assumes you'll have a max of 20 columns in the table
#for $i from 1 through 20{
td:nth-child(#{$i}){
background-color: opacify(rgba(0,0,0,0), $i*.04)
}
}
Here's a demonstration on codepen: http://codepen.io/noraspice/pen/doEyJq?editors=110.

Middle Child Pseudo-Class

Is there a way to use CSS selectors to get the middle child in a list of elements?
I know that there is no literal :middle-child selector, but is there another way without resorting to Javascript?
This has been working well for me:
*:not(:first-child):not(:last-child) {
...
}
You can see an example of this here: http://codepen.io/bentomas/pen/Gwqoe
The one caveat to this is that it only works in IE 9+: http://caniuse.com/#feat=css-sel3
While not elegant, if you know the upper and lower limits of the total number of elements, you could take a brute force approach to select the middle element.
For example, the following rules will select the middle element in a set of 5, 7, or 9 elements.
div:nth-child(3):nth-last-child(3) {
/* The middle element in a set of 5 is the 3rd element */
}
div:nth-child(4):nth-last-child(4) {
/* The middle element in a set of 7 is the 4th element */
}
div:nth-child(5):nth-last-child(5) {
/* The middle element in a set of 9 is the 5th element */
}
Or with Sass:
#for $i from 3 through 5 {
div:nth-child(#{$i}):nth-last-child(#{$i}) {
/* The middle element */
}
}
You can use the "not first and not last" approach, like so:
CSS
li:not(:first-child):not(:last-child) {
color:red;
}
HTML
<ul>
<li>First</li>
<li>Second</li>
<li>Third</li>
</ul>
Check the JsFiddle
If you want to apply a style to all elements that are neither first children nor last children, you could use :not(:first-child), apply the style, and then use :last-child to 'take the style away' from the last element. But you'd have to think about what happens when there are less than 3 elements.
I've encountered the need to target the middle child on several occasions, and I've taken to using this sass mixin I wrote after referencing many similar questions, and their respective answers.
// Generate a reasonable number rules limited by $n.
#mixin middle-child($n) {
// There is no middle for nChildren less than 3,
// so lets just start at 3.
#for $i from 3 to $n {
// Find the middle, bias right for odd numbers.
$mid: math.ceil(math.div($i, 2));
// Select only those sets of children that number $i.
&:first-child:nth-last-child(#{$i}) {
// Select the middle child of that set.
~ :nth-child(#{$mid}) {
#content; // Apply your styles.
}
}
}
}
Usage:
.navigation {
background-color: #ba0020;
.nav-item {
color: white;
#include middle-child( 8 ) {
font-weight: 900;
}
}
}
Have you tried :nth-child(#) ?
Depending on which one you want to select you just replace # with the number.
Javascript is the only way to do this client side.

Style the first <td> column of a table differently

If I have a table with two columns, how do I specify a padding or any other css so that it is applied just for the first column of <td>s. Also how do I style an n-th column similarly?
You could use the n-th child selector.
to target the nth element you could then use:
td:nth-child(n) {
/* your stuff here */
}
(where n starts at 1)
The :nth-child() and :nth-of-type() pseudo-classes allows you to select elements with a formula.
The syntax is :nth-child(an+b), where you replace a and b by numbers of your choice.
For instance, :nth-child(3n+1) selects the 1st, 4th, 7th etc. child.
td:nth-child(3n+1) {
/* your stuff here */
}
:nth-of-type() works the same, except that it only considers element of the given type ( in the example).
For more information about nth-child
https://developer.mozilla.org/es/docs/Web/CSS/:nth-child
If you've to support IE7, a more compatible solution is:
/* only the cells with no cell before (aka the first one) */
td {
padding-left: 20px;
}
/* only the cells with at least one cell before (aka all except the first one) */
td + td {
padding-left: 0;
}
Also works fine with li; general sibling selector ~ may be more suitable with mixed elements like a heading h1 followed by paragraphs AND a subheading and then again other paragraphs.
This should help. Its CSS3 :first-child where you should say that the first tr of the table you would like to style. http://reference.sitepoint.com/css/pseudoclass-firstchild
To select the first column of a table you can use this syntax
tr td:nth-child(1n + 2){
padding-left: 10px;
}

CSS3: Reset alternate table row coloring after a certain class of tr

Here's my fiddle.
http://jsfiddle.net/cnLDF/
I want every .content row after each .heading row to start with gray, in this case, "content 5".
How do I do it by modifying the CSS only.
Using the adjacent sibling selector (i used red color for demo purposes):
table tr.heading + tr.content {
background: #f00;
}
But note that the nth-child(even) will win, then you will colour only the first .content, preceeded by an .header, that is odd (and not even).
Demo: http://jsfiddle.net/cnLDF/1/
EDIT:
I've tried a bit, and I don't think it's possible with pure CSS (but i'll be happy to be proven wrong): pseudo-elements will always refer to all tr elements in the table (with odd and even), and the last declaration will override the previous... the only way with CSS only imho is to create a static declaration for every case with adjacent selector after every heading, that is doable only if you have a small, known, fixed number of content for every heading (let's say 5, or 10...), like this:
table tr.heading + tr.content > td {/* stuff */ }
table tr.heading + tr.content + tr.content > td {/* stuff */ }
table tr.heading + tr.content + tr.content + tr.content > td {/* stuff */ }
/* and so on... */
If instead you could handle the input, you could easily calculate the output serverside, applying "odd" and "even" classes to trs, and coloring them accordingly.

SCSS setting a value based upon another

I'm just trying to work out if something is possible or not with SCSS.
Please feel free to ask me for more details if I'm not very clear in what I'm asking, but here's what I'm trying to achieve.
Pseudo code:
.class1 { width:100px; }
.class2 { margin-right:[.class1{width}] + 2 }
compiling into
.class1 {width:100px; }
.class2 { margin-right:102px; }
I believe to get what you want, a variable is best used:
$yourWidth: 100px;
.class1 { width: $yourWidth; }
.class2 { margin-right: ($yourWidth + 2); }
Update (based on comment info)
You might add a global variable below $ColCount that begins as an empty list, like so:
$WidthList: ();
Then inside #mixin columns($numCols) after $colWidth is calculated, add the width value for that column to the $WidthList by adding this function:
join($WidthList, $colWidth);
Then, once all the columns have calculated, you should have a list containing all the width values, so that you can access them if you desire elsewhere, and thus...
.class2 { margin-right: (nth($WidthList, 5) + 2); }
...should yield the .cl-col5 value you want for the margin.
Note that I did not test this. Nor have I actually ever used SASS. I am basing this strictly off the documentation found here and elsewhere on their site.

Resources