27

I want to give a zebra stripe effect to my table rows. In all other browsers it can be done using CSS nth child element. But i want to do it IE 8 also. SO how can i do it?

avalkab
  • 436
  • 3
  • 18
surajR
  • 573
  • 2
  • 7
  • 18

4 Answers4

57

With polyfill : Selectivizr is good enough.

Without polyfill: As IE8 supports first-child you can trick this to support nth-child in iE8 i.e

/*li:nth-child(2)*/
li:first-child + li {}/*Works for IE8*/

Although we cannot emulate complex selectors i.e nth-child(2n+1) or nth-child(odd) for IE8.

Samar Panda
  • 4,186
  • 3
  • 25
  • 32
  • This works for my second row, but what if I have multiple divs in rows and I want to color every other one, no matter the number of them? – user1997781 Oct 14 '13 at 22:20
  • 2
    @user1997781 As i said earlier this hack cannot emulate complex selectors for IE8 i.e Doesn't support nth-child(2n+1) or nth-child(odd). – Samar Panda Oct 16 '13 at 15:10
  • Since the '+' selector is additive, you can emulate ':nth-child' to an arbitrary number of items above by adding '+ li' for each extra item, so 'li:nth-child(4)' becomes 'li:first-child + li + li + li' – Patanjali Jul 28 '16 at 06:04
  • @Patanjali Agree with you when you want to target single odd / even child. But when you want to write this for each child explicitly in our stylesheet that would be tough, impractical to target each rows with li + li + ... n. – Samar Panda Feb 12 '17 at 07:05
  • @SamarPanda. AS you said, there IS no way to emulate the process for an arbitrary number, which is why the special formats were invented. Rock and a hard case here. The OP will have to live with it. – Patanjali Feb 14 '17 at 06:10
36

As an alternative to Selectivizr, you can use a little jQuery:

$('.your-list li:nth-child(3n+1)').addClass('nth-child-3np1');

Then just add a second selector in your CSS:

:nth-child(3n+1)
{
    clear: both;
}

.nth-child-3np1
{
    clear: both;
}
Aaron Cicali
  • 1,496
  • 13
  • 24
Jonathan
  • 18,229
  • 10
  • 57
  • 56
  • 3
    To add to this, you can use conditional comments to place an oldIE class on body and then only execute that jQuery snippet if that class is present. – Michael Cordingley Oct 15 '13 at 15:52
  • 2
    Also worth noting, IE7 and IE8 will ignore a statement which includes unsupported pseudo-classes (such as the one above). To get around it, you need to re-declare things separately. http://stackoverflow.com/questions/21856542/internet-explorer-ie7-ie8-ignoring-css-rule-with-nth-child-in-comma-separated – Michel Joanisse Sep 06 '14 at 12:58
26

You can use http://selectivizr.com/ JS which support css3 selector for IE.

sandeep
  • 91,313
  • 23
  • 137
  • 155
  • 1
    Curiously, [IE9.js](http://code.google.com/p/ie7-js/) allegedly enables [`:nth-child()` support](http://ie7-js.googlecode.com/svn/test/nth-child.html), but it does not work in practice. – Tomalak May 14 '12 at 05:23
  • 1
    @sandeep I used selectvizr.js but it is not working if i have two table on one page. It works for one table but not other – surajR May 16 '12 at 14:03
2

The 'first-child' and '+' selectors are both available in IE7, and the '+' is additive.

Therefore 'nth-child' can be simulated by successively adding '+' selectors, so:

tr:nth-child(4)

becomes:

tr:first-child + tr + tr + tr

If all sibling elements are the same, then the '*' wildcard will suffice, as in:

tr:first-child + * + * + *

which will reduce the css file size if specifying lots of rows.

Note that spaces between selectors are not required, so the file size can be reduced further by leaving them out, so to select the 1st, 3rd and 5th rows:

tr:first-child,tr:first-child+*+*,tr:first-child+*+*+*+*

Of course one would not want to cater for very large tables!

If using the * as a filler, make sure the :first-child element and the last element is given the explicit tagname, because the rule will be tested against every element in the DOM, and specifying both those elements explicitly forces failure at whichever end a particular browser applies its rules to first, rather than failing after it has had to step over several elements in every sequence to eventually fail the rule for each of them. Don't make your browser work for no good reason!

Patanjali
  • 893
  • 13
  • 17
  • Not quite. `tr:nth-child(4)` would be equivalent to `*:first-child + * + * + tr`. – Marnen Laibow-Koser Jan 22 '17 at 18:02
  • @MarnenLaibow-Koser. If, as stated, the elements are the same tag name, why is there a need to make the last `tr`? – Patanjali Jan 25 '17 at 10:17
  • Can you rephrase your question? I'm not sure I understand what you're getting at. – Marnen Laibow-Koser Jan 25 '17 at 15:57
  • @MarnenLaibow-Koser. Why is a starting `*` instead of a `tr`, and a final `tr` instead of a `*`, better, especially when the condition was that they were all `tr`s anyway? – Patanjali Jan 26 '17 at 07:28
  • @MarnenLaibow-Koser. Only one needs to be a `tr` to ensure the rule applies, so any version with at least one `tr` is equivalent. Basically, the first one is the best to specify explicitly, as the rule engine can have the opportunity to reject the rule applying to any particular instance early on. – Patanjali Jan 26 '17 at 07:34
  • @MarnenLaibow-Koser. For example, the rule as you have written it will be tested against any `li` elements in a list, a bunch of `p`s on a page, and it will have to get to the fourth element to eventually fail it. Put the most restrictive test first, which forces failure on the first element for each sequence that doesn't start with a `tr`. – Patanjali Jan 26 '17 at 07:41
  • "Why is a starting `*` instead of a `tr`, and a final `tr` instead of a `*`, better" • Because that is actually how the `:nth-child` pseudoclass works: it refers to the nth child of its parent *regardless of the children's types*. `tr:nth-child(4)` doesn't mean the 4th `tr` child; it means the 4th child, if it's of type `tr`. – Marnen Laibow-Koser Jan 27 '17 at 12:58
  • "Put the most restrictive test first" • First of all, in this example, I'm worried about correctness, not efficiency. Second, "first" doesn't mean "left". The CSS spec doesn't require left-to-right selector evaluation, and apparently most browsers evaluate CSS selectors from right to left: see http://stackoverflow.com/questions/5797014/why-do-browsers-match-css-selectors-from-right-to-left . – Marnen Laibow-Koser Jan 27 '17 at 13:06
  • In this particular case, the difference between specifying the `tr` tag name and using `*` would be minimal, because `tr` elements occur only in contexts where no other element is valid. But if you're going to use a selector, it's important to understand what it actually means... – Marnen Laibow-Koser Jan 27 '17 at 13:30
  • @MarnenLaibow-Koser. I realise you are examining this is absolute terms, but I am dealing with equivalences in results, not pedantically exact, if it doesn't make any difference, which is what my caveat (all `tr`) basically did. However, if indeed browsers do evaluate RTL, then an explicit last is the best (I have seen a lot of opinions, though not an explicit reference to a sentence in a browser spec that states RTL exclusively. Boris Zbarsky seems to indicate that there is quite a mixture in https://groups.google.com/forum/#!topic/mozilla.dev.tech.layout/sYXkVaCzVio). – Patanjali Jan 28 '17 at 00:13