1

I have a problem with CSS :nth-of-type selector. In my code I have a list of DIVs (class "item") that should have an alternating background-color (eg. red and green). Between these items there can be some other items (class "noitem") that should not be matched from the background-color.

Problem is now, that the :nth-of-type rule breaks on every of these non-matching elements. that causes that you have one red item after the other...

Example HTML Code:

<div class="row">
  <div class="item"><h2>Item</h2></div>
  <div class="item"><h2>Item</h2></div>
  <div class="noitem"><h2>No Item</h2></div>
  <div class="item"><h2>Item</h2></div>
  <div class="item"><h2>Item</h2></div>
  <div class="item"><h2>Item</h2></div>
  <div class="item"><h2>Item</h2></div>
  <div class="noitem"><h2>No Item</h2></div>
  <div class="item"><h2>Item</h2></div>
  <div class="item"><h2>Item</h2></div>
</div>

CSS:

h2{
  font-size: 14px;
  margin: 0 0 10px 0;
  padding: 0;
}

.row .item:nth-of-type(even) h2{
  background-color: red;
}

.row .item:nth-of-type(odd) h2{
  background-color: green;
}

Can anybody help? Running example of that can be found here: http://jsfiddle.net/5qnjshg7/

Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
Philip
  • 159
  • 2
  • 15
  • possible duplicate of [css3 nth of type restricted to class](http://stackoverflow.com/questions/10921809/css3-nth-of-type-restricted-to-class) – Pete Dec 05 '14 at 10:49

3 Answers3

3

The type in nth-of-type refers to the type of element (tag name, such as div). It does not mean "nth-of-something-with-exactly-the-same-classes", or "nth-of-the-selector-I-specified", which does not exist in CSS.

In other words, .item:nth-of-type(even) does not mean "an even-numbered entry in the list of all child elements with class .item", but rather, "an element with class .item which also is in an even-numbered position in the list of all child elements of that type (div in this case), regardless of their class or anything else".

One possible approach if you're stuck with the existing HTML

If you can generate different HTML, including for example new classes, or replacing the div on noitem elements with spans, as one answer suggested, then that is the best solution. In case you are not able to do or don't want to do that, and need to work with the existing HTML for whatever reason, this bit of JS will do the job:

var elts = document.querySelectorAll('div.item');
for (var i = 0; i < elts.length; i++) {
    elts[i].classList.add(i % 2 ? 'red' : 'green');
}
  • There is absolutely no need to add javascript for this. – Michael Tempest Dec 09 '14 at 08:49
  • @MichaelTempest What is your approach then? –  Dec 09 '14 at 08:50
  • Simply add the classes to the DOM, its basic HTML, why use a javascript loop to get all the elements. Also if he is dynamically generating them, then it is easy to do in that format too – Michael Tempest Dec 09 '14 at 08:52
  • 1
    Well, the OP was asking why the CSS `nth-of-type` pseudo-class did not behave as he expected. The first 2/3 of my answer was answering that. As far as the bit of JS here, I'm not suggesting it is the only or optimal solution, but it's one way to deal with the situation which could be useful especially if he has no control over the generated HTML, as is sometimes the case. I've fine-tuned the wording in my answer accordingly. –  Dec 09 '14 at 09:10
1

nth-of-type matches the element to its parent, so although it is not the same selector, it is in fact the correct index relevant to its parent.

Michael Tempest
  • 814
  • 7
  • 12
1

Seems impossible with CSS, unless you can change your markup and make noitem elements <span>s?

<div class="row">
    <div class="item"><h2>Item</h2></div>
    <div class="item"><h2>Item</h2></div>
    <span class="noitem"><h2>No Item</h2></span>
    <div class="item"><h2>Item</h2></div>
    <div class="item"><h2>Item</h2></div>
    <div class="item"><h2>Item</h2></div>
    <div class="item"><h2>Item</h2></div>
    <span class="noitem"><h2>No Item</h2></span>
    <div class="item"><h2>Item</h2></div>
    <div class="item"><h2>Item</h2></div>
</div>