Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pure CSS3 solution to stripe table with multiple <tbody> elements?

Tags:

html

css

I've got a table with multiple <tbody> elements. At a given time, only one <tbody> is displayed, or all of them are displayed.

I currently use this CSS3 code to stripe the table:

table tr:nth-child(even) {
  background: #efefef;
}

When a single <tbody> element is shown, everything is (obviously) fine, but when multiple <tbody> elements are shown the CSS rules apply to each one separately, and each <tbody> has its own “stripes system”. Together the stripes may or may not look consistent, depending on the number of rows.

<tbody>
  <tr> [ODD]
  <tr> [EVEN]
  <tr> [ODD]
</tbody>
<tbody>
  <tr> [ODD]
  <tr> [EVEN]
</tbody>
…

Would I absolutely have to use JavaScript (… jQuery) to fix this? Or is there a pure CSS solution?

like image 310
xyz Avatar asked May 30 '10 23:05

xyz


People also ask

Can you have multiple tbody in a table?

You may use more than one <tbody> per table as long as they are all consecutive.

Which CSS would correctly apply the background Colour to every odd row in your table?

Tap into the tr (table row) element is CSS. Use the nth-child() selector and add background-color of your choice to all odd (or even) table rows.


3 Answers

If you're using jQuery then use the :even selector, (edited: to handle visibility) like this:

$("table tr:visible:even").addClass("even");​ 

And a class like this:

.even { background: #efefef; } 

Again, that's if you're using jQuery already, if you're not go with a pure javascript solution (including any library for just this is overkill) like bobince posted. Either way I don't see a pure CSS solution here...it's definitely a valid case, but not something that comes up often enough to make it spec-worthy.

like image 171
Nick Craver Avatar answered Nov 07 '22 04:11

Nick Craver


If you have rows that are all the same height, you can cheat with a gradient, e.g.:

#table {
    background-image: repeating-linear-gradient(pink 0, pink 1.6em, yellow 1.6em, yellow 3.2em);
    background-repeat: no-repeat;

    /* To account for headers; adjust size to account for footers.
     * You can also use a second (or third) gradient for both.
     */
    background-position: 0 1.4em;
}

If you can guarantee that all <tbody> elements have an even number of rows, you can also make use of that (even if the last one is hidden), but otherwise, you’re out of luck. Selectors Level 4 might have something to say about it, though, with something along the lines of

#table > !tbody > tr:last-child:nth-child(even)

making up for the class.

Demo!

like image 35
Ry- Avatar answered Nov 07 '22 03:11

Ry-


After intensive research, I can state that

There is no pure CSS3 (not even CSS4) solution to match even/odd rows accross multiple parents.

All solutions you would think of are impossible:

  1. Use the :nth-child pseudo-class.

    Verdict: This will only work within a single parent.

  2. Somehow involve the tbody tags with odd number of rows (color switchers) by counting their children and distinguishing those with odd rows in a similar way nth-child(odd) works.

    Verdict: In CSS it is not possible to count children, see this question. Beware of the confusing accepted answer - this is in fact counting siblings, not children

  3. Try to match only some tbodys based on some children CSS rule, and thus being able to identify tbodys with odd number of children.

    Verdict: In CSS it is not possible to match elements according to their children:

    • Apply CSS styles to an element depending on its child elements
    • Complex CSS selector for parent of active child
    • Is there a CSS parent selector?
    • Select element based on child class
  4. CSS4 introduces a new selector :nth-match, which sounds promising as it doesn't contain the word "child" in it. So you would wonder if this would work:

:nth-match(even of tr) { background-color: #ccc; }
:nth-match(odd of tr) { background-color: #fff; }

Verdict: It doesn't work. If you look at the description, you see it will do exactly the same thing you observe:

The :nth-match(An+B of <selector>)pseudo-class notation represents an element that has An+B-1 siblings that match the given selector list before it in the document tree.

The problematic is the word siblings which mean it will only count within each tbody tag, as the :nth-child selectors do.

Conclusion

There is no pure CSS (neither CSS3 nor CSS4) solution. You will have to refrain to either:

  • javascript, e.g. the great jQuery solution mentioned by Nick Craver;
  • minitech's background trick, but its use is limited to equal-height rows;
  • changes in the HTML generation code.
like image 45
Tomas Avatar answered Nov 07 '22 04:11

Tomas