0

What is the rule counting with :nth-child()? Is it simply a bug?

.info_row:nth-child(even) {
  background: orange
}
<div>
  <h2>Title</h2>
  <div class="info_row">
    <div>Category:</div>
    <div>data</div>
  </div>
</div>

If I wrap div.info_row in other <div> or delete <h2> it is obvious, that .info_row:nth-child(even) is being counted with <h2> without .info_row class.

Vadim Ovchinnikov
  • 13,327
  • 5
  • 62
  • 90
Zydnar
  • 1,472
  • 18
  • 27
  • 5
    its select the whole info_row-div, so everything is orange youre missing a space `.info_row :nth-child(even)` – fehrlich Aug 02 '17 at 13:29
  • Pseudo-classes like `nth-child` match elements, not classes of elements. Adding a class makes it act like a filter and it becomes more restrictive. Plus, the actual selector is applied to the `.info_row` element, not it's children. – j08691 Aug 02 '17 at 13:30
  • This might help https://developer.mozilla.org/en/docs/Web/CSS/:nth-child – winner_joiner Aug 02 '17 at 13:31
  • What if I want every even .info_row not its children to be affected by the rule? – Zydnar Aug 02 '17 at 13:33
  • Why this works as expected: https://jsfiddle.net/Zydnar/xuoxe6mj/1/ – Zydnar Aug 02 '17 at 13:40
  • @Zydnar Because it is highlighting the info_row that is an even-child of info_row's parent. `nth-child` has more complex rules than you are realizing. – TylerH Aug 02 '17 at 13:42
  • @TylerH but in the fiddle in the link the parent has no class so I can't understand "the info_row that is an even-child of info_row's parent", do you? – Zydnar Aug 02 '17 at 13:44
  • `nth-child` doesn't care about classes. It cares about children. You adding a class like `.info_row:nth-child(2)` just restricts how many times it will *match* your elements. The logic behind how `nth-child(2)` works doesn't change just because you threw a class in front of it. `.info_row:nth-child(2)` will match *only* the elements that are even children of a parent *AND* who have the `.info_row` class. – TylerH Aug 02 '17 at 13:46
  • @TylerH this is the answer, thank you. – Zydnar Aug 02 '17 at 13:47
  • @TylerH: Ironically, :nth-child() is as straightforward as it can possibly get - it's authors that read too much into it and overcomplicate it as a result. – BoltClock Aug 02 '17 at 14:10

4 Answers4

5

You are using the :nth-child() selector, whereas you should be using the :nth-of-type() selector:

.info_row:nth-of-type(even) {
  background: orange
}
<div>
  <h2>Title</h2>
  <div class="info_row">
    <div>Category:</div>
    <div>data</div>
  </div>
  <div class="info_row">
    <div>Category 2:</div>
    <div>data</div>
  </div>
</div>

Explanation

The :nth-of-type() selector selects the n-th child of a parent element that corresponds to the specific type (i.e. a div tag). On the other hand, the :nth-child() selector select the n-th child of a parent element, regardless of type, thus counting the h2 element, too.

Angelos Chalaris
  • 6,611
  • 8
  • 49
  • 75
  • Your explanation is correct, but your assumption of what OP wants appears to be incorrect. – TylerH Aug 02 '17 at 13:35
  • @TylerH Updated, this should be the proper solution that OP wants. – Angelos Chalaris Aug 02 '17 at 13:37
  • Your original explanation was correct, the one you've now added is incorrect... – BoltClock Aug 02 '17 at 14:08
  • @BoltClock I'm pretty confused right now, as I am reading the OP's question over and over. Does he/she not want to have the even `.info_row` elements colored orange? I would really like to update my answer to the right one, which I clearly can do, but the whole question explaining has got me confused right now. Also, the answer was marked accepted after the last edit... – Angelos Chalaris Aug 02 '17 at 14:10
  • The "type" in :nth-of-type() does not refer to "the rest of the selector". The "type" refers to the tag name. – BoltClock Aug 02 '17 at 14:12
  • Aha, @BoltClock, I see what you mean, I will take a second to update this. Thank you! – Angelos Chalaris Aug 02 '17 at 14:19
4

What You are selecting is the nth-child of the same element so you can give it a space like that .info_row :nth-child(even) which means the nth of its children or add the child div like that .info_row >div:nth-child(even)

.info_row >div:nth-child(even) {
  background: red;
}
<div>
  <h2>Title</h2>
  <div class="info_row">
    <div>Category:</div>
    <div>data</div>
  </div>
</div>
lotfio
  • 1,916
  • 2
  • 18
  • 34
2

Try This :

.info_row div:nth-of-type(even) {
  background-color: orange;
} 
<div>
  <h2>Title</h2>
  <div class="info_row">
    <div>Category:</div>
    <div>data</div>
  </div>
</div> 

OR

.info_row div:nth-child(even) {
  background-color: orange;
}
<div>
  <h2>Title</h2>
  <div class="info_row">
    <div>Category:</div>
    <div>data</div>
  </div>
</div>
Ehsan
  • 12,655
  • 3
  • 25
  • 44
2

.class:nth-child(x) doesn't mean "select the number x between the .class elements", it means "select all the .class elements which are the number x of its parent".

For example, div:first-child will not select the div in:

<p>foo</p>
<div>bar</div>
TylerH
  • 20,799
  • 66
  • 75
  • 101
Fla
  • 536
  • 6
  • 23