最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - :nth-child(2) doesn't work. :nth-child(1) and :nth-child(3) do - Stack Overflow

programmeradmin1浏览0评论

:nth-child(2) seems to select something inside of child 1.

child 1 and child 3 work correctly.

It doesn't seem to involve the type of tag, as several similar but different questions do. I don't see the problem.

/

var one = document.querySelector('div.rules :nth-child(1)');
var two = document.querySelector('div.rules :nth-child(2)');
var three = document.querySelector('div.rules :nth-child(3)');
one.classList.add('arule');
two.classList.add('brule');
three.classList.add('crule');
.arule {
  background-color: yellow;
}

.brule {
  background-color: red;
}

.crule {
  background-color: blue;
}
<div class="rules">
  <div>
    <label for="rule1">Rule1</label>
    <input id="rule1">
  </div>
  <div>
    <label for="rule2">Rule2</label>
    <input id="rule2">
  </div>
  <div>
    <label for="rule3">Rule3</label>
    <input id="rule3">
  </div>
</div>

:nth-child(2) seems to select something inside of child 1.

child 1 and child 3 work correctly.

It doesn't seem to involve the type of tag, as several similar but different questions do. I don't see the problem.

https://jsfiddle/rhedin/em56jk9v/

var one = document.querySelector('div.rules :nth-child(1)');
var two = document.querySelector('div.rules :nth-child(2)');
var three = document.querySelector('div.rules :nth-child(3)');
one.classList.add('arule');
two.classList.add('brule');
three.classList.add('crule');
.arule {
  background-color: yellow;
}

.brule {
  background-color: red;
}

.crule {
  background-color: blue;
}
<div class="rules">
  <div>
    <label for="rule1">Rule1</label>
    <input id="rule1">
  </div>
  <div>
    <label for="rule2">Rule2</label>
    <input id="rule2">
  </div>
  <div>
    <label for="rule3">Rule3</label>
    <input id="rule3">
  </div>
</div>

Share Improve this question edited Jan 15, 2019 at 23:14 Temani Afif 275k28 gold badges366 silver badges486 bronze badges asked Jan 15, 2019 at 21:46 user2171796user2171796 4374 silver badges17 bronze badges 1
  • Please don't edit your question to include your answer or how you understand this based on the answers you got. Either ask for clarification in case you didn't get everything (using ments) or answer you own question if you want to provide your version of answer – Temani Afif Commented Jan 15, 2019 at 23:16
Add a ment  | 

6 Answers 6

Reset to default 4

try like this:

var one   = document.querySelector('div.rules div:nth-child(1)');
var two   = document.querySelector('div.rules div:nth-child(2)');
var three = document.querySelector('div.rules div:nth-child(3)');
one.classList.add('arule');
two.classList.add('brule');
three.classList.add('crule');
.arule {
  background-color: yellow;
}
.brule {
  background-color: red;
}
.crule {
  background-color: blue;
}
  <div class="rules">
    <div>
      <label for="rule1">Rule1</label>
      <input id="rule1">
    </div>
    <div>
      <label for="rule2">Rule2</label>
      <input id="rule2">
    </div>
    <div>
      <label for="rule3">Rule3</label>
      <input id="rule3">
    </div>
  </div>

I made div.rules div:nth-child(2)

Here is an explanation of what went wrong. It was the result of your selector. The oddity in the way it played out was due to your html structure, and using querySelector.

div.rules :nth-child()

This will first target the <div class="rules"> element. Then, it will look for all elements which are the nth-child inside of that div because of the space between the two selectors. Following that, using querySelector will select the first element of the matched set.

This is why you ended up getting the first <div> with :nth-child(1), because it in fact matched every single nth-child(1), but taking the first result was coincidentally the element you expected.

However, :nth-child(2) matching every second child element was far too wide of a net, and ended up getting the second child in the first div, and since that was the first result, that was where the red background showed up.

The final curiosity of :nth-child(3) seeming to actually hit the proper element was only because there is only one third child element in all of that html, and it was the one which you expected, although as explained for reasons other than assumed.

document.querySelector will return one element and as you can see your input is red because the rule div.rules :nth-child(2) apply to it as it's the second child inside his parent element, so you will select it (since it es first in the DOM tree) and not the div.

You should use > selector if you want to target only the divs or use div:nth-child() or consider document.querySelectorAll to get all the elements that match the selector:

var one = document.querySelector('div.rules > :nth-child(1)');
var two = document.querySelector('div.rules > :nth-child(2)');
var three = document.querySelector('div.rules > :nth-child(3)');
one.classList.add('arule');
two.classList.add('brule');
three.classList.add('crule');

/*this will add border to all inputs and second div*/
var all = document.querySelectorAll('div.rules  :nth-child(2)');
for(var i=0;i<all.length;i++) {
  all[i].style.border="3px solid green";
}
.arule {
  background-color: yellow;
}

.brule {
  background-color: red;
}

.crule {
  background-color: blue;
}
<div class="rules">
  <div>
    <label for="rule1">Rule1</label>
    <input id="rule1">
  </div>
  <div>
    <label for="rule2">Rule2</label>
    <input id="rule2">
  </div>
  <div>
    <label for="rule3">Rule3</label>
    <input id="rule3">
  </div>
</div>

You want to be targeting only the direct children of div.rules. Since you're using querySelector, it only returns the first result, for :nth-child(2), that's the input in the first div (you'll notice that it has a red background in your example)

var one = document.querySelector('div.rules > :nth-child(1)');
var two = document.querySelector('div.rules > :nth-child(2)');
var three = document.querySelector('div.rules > :nth-child(3)');
one.classList.add('arule');
two.classList.add('brule');
three.classList.add('crule');
.arule {
  background-color: yellow;
}

.brule {
  background-color: red;
}

.crule {
  background-color: blue;
}
<div class="rules">
  <div>
    <label for="rule1">Rule1</label>
    <input id="rule1">
  </div>
  <div>
    <label for="rule2">Rule2</label>
    <input id="rule2">
  </div>
  <div>
    <label for="rule3">Rule3</label>
    <input id="rule3">
  </div>
</div>

A simple solution would be to add a plain div in your selector (jsfiddle)

var one   = document.querySelector('div.rules div:nth-child(1)');
var two   = document.querySelector('div.rules div:nth-child(2)');
var three = document.querySelector('div.rules div:nth-child(3)');
one.classList.add('arule');
two.classList.add('brule');
three.classList.add('crule');

There is a awesome website about this kind of selector. You should definitly give it a shot: CSS Diner.

At least specify that you mean direct children, as there may be multiple nested ones, and program can't find out what you mean:

var one   = document.querySelector('div.rules > :nth-child(1)');
var two   = document.querySelector('div.rules > :nth-child(2)');
var three = document.querySelector('div.rules > :nth-child(3)');
one.classList.add('arule');
two.classList.add('brule');
three.classList.add('crule');
发布评论

评论列表(0)

  1. 暂无评论