Различия между :nth-child и :nth-of-type

Original author: Chris Coyier
  • Translation
Допустим, есть такой HTML:
<section>
   <p>Little</p>
   <p>Piggy</p>    <!-- Нужен этот элемент -->
</section>

Следующий CSS будет делать одно и тоже:
p:nth-child(2) { color: red; }

p:nth-of-type(2) { color: red; }


Хотя, конечно, в этих селекторах, есть разница.

Псевдокласс :nth-child, означачает выбрать элемент, если:
  1. Этот элемент — параграф;
  2. Это второй элемент одного родителя.

Псевдокласс :nth-of-type, означает:
  1. Выбрать второй параграф одного родителя.

Предположим, что наша разметка изменена следующим образом:
<section>
   <h1>Words</h1>
   <p>Little</p>
   <p>Piggy</p>    <!-- Нужен этот элемент -->
</section>

Теперь первый вариант не работает:
p:nth-child(2) { color: red; } /* Не работает */

Второй продолжает работать:
p:nth-of-type(2) { color: red; } /* Продолжает работать */

Под «Не работает» я имею ввиду, что cелектор :nth-child выбирает слово «Little» вместо «Piggy». Потому что элемент выполняет оба условия: 1) Это второй элемент родительского элемента и 2) Это параграф. Под «Продолжает работать», я имею ввиду, что селектор продолжает выбираться «Piggy», потому что это второй параграф родительского элемента.

Если добавить <h2> после <h1>, то селектор с :nth-child не выберет ничего, потому что параграф больше не является вторым элементом. Селектор с :nth-of-type продолжит работать.

Мне кажется :nth-of-type менее хрупкий и более полезный в целом, несмотря на это :nth-child продолжает быть основным в работе. Как часто вы думаете «Я хочу выбрать второй элемент в родительском блоке, если это параграф». Возможно иногда, но чаще вы думаете «Выбрать второй параграф» или «выбрать каждую третью строку таблицы», для этих задач больше подходит :nth-of-type (опять же, на мой взгляд).

Большинство ситуаций, когда я говорю «Почему мой селектор с :nth-child не работает?» случаются из за того, что я забываю про выборку тегов и нужный тег не оказывается по счету тем, который нужен. Поэтому, при использовании :nth-child лучше указывать его от родителя и не использовать привязку к тегу.
dl :nth-child(2) {  } /* Этот вариант лучше чем */
dd:nth-child(2) {  } /* этот */

Но, конечно, все зависит от конкретной ситуации.

Поддержка браузерами :nth-of-type довольно приличная… Firefox 3.5+, Opera 9.5+, Chrome 2+, Safari 3.1+, IE 9+. Я бы сказал, если вам нужна более глубокая поддержка, то используйте jQuery (используйте селектор и применяйте класс, там где нужно), но jQuery прекратил поддержку :nth-of-type. Слышал, что из за редкого использования, но мне это кажется странным. Если вы хотите пойти этим путем, то вот плагин возвращающий поддержку назад.
Share post

Similar posts

Comments 16

    0
    > «но jQuery прекратил поддержку :nth-of-type. Слышал, что из за редкого использования, но мне это кажется странным»

    У Jquery есть более универсальные средства, которые в частности реализуют и данный функционал.

      0
      чтоб быть более точным, jQuery использует движок Sizzle, а тот в свою очередь не поддерживает nth-of-type.
      в jQuery это можно реализовать как $('p:odd') для четных и $('p:even') для нечетных.
        +1
        Jquery очень гибок.
        Например:
        $('p').eq(2) // выбрать второй параграф.
          +12
          кстати третий.
          $('p').eq(1) Вот это второй
          0
          А если через три надо выбрать? Или начиная со второго, например?
            0
            если начиная с индекса N то p:gt(N-1)
              0
              Я вообще имел в виду через три начиная со второго, но так тоже можно :)
              0
              а если каждый третий то уже надо ухищряться, например так
              $('p').each(function(i){
              if(i%3==0) return;
              ///делаем что хотим
              )}
          –1
          спасибо, то что нужно!
            0
            А вообще, что селектор :nth-of-type подразумевает под type? Имя тега? Получается, что селектор .class:nth-of-type(2) бессмысленный, потому что не задает какой именно нужно тип выбрать? Или же в данном случае типом будет считаться .class?
              0
              Судя по описанию w3c, под type понимается элемент, тоесть тег.
              www.w3.org/TR/css3-selectors/#nth-of-type-pseudo
              Но проверил, в случае описаном вами firefox, safari и chrome выберут второй элемент, если у него есть класс .class
                +1
                Селекторы всегда относятся к тому элементу, который задан до них. В случае p:nth-of-type(x) это будет тег P, в случае table .info:nth-of-type(x) будет любой тег с классом .info внутри таблиц.
                  –1
                  К сожалению ни nth-child, ни nth-of-type с классами и атрибутами не работают — только элементы.
                  Т.е. если у вас часть строк таблицы скрыты, то нельзя правильно сделать зебру средствами CSS для оставшихся видимых строк с определённым назначенным классом.
                0
                Спасибо за перевод!

                (А Между тем у меня были ситуации, когда «:nth-child» не работал «по странным обстоятельствам» :-).
                  –14
                  битрикс
                    0

                    Only users with full accounts can post comments. Log in, please.