В чем разница между p:nth-child(2) и p:nth-of-type(2)?
В чем разница между p:nth-child(2)
а также p:nth-of-type(2)
?
В соответствии с W3Schools CSS Selector
p:nth-child(2)
: Выбирает каждый<p>
элемент, который является вторым дочерним элементом своего родителя.p:nth-of-type(2)
: Выбирает каждый<p>
элемент, который является вторым<p>
элемент его родителя.
Разница, кажется, является дочерью своего родителя и <p>
элемент его родителя.
Если мы уже упоминаем тип элемента как <p>
в обоих случаях ключевое слово parent устанавливает отношение родитель-потомок, в чем же может быть разница?
8 ответов
Этот вопрос может напомнить вам о том, в чем разница между:first-child и:first-of-type? - и на самом деле между ними можно провести много параллелей. Где этот вопрос сильно отличается от другого - произвольный целочисленный аргумент X, как в :nth-child(X)
а также :nth-of-type(X)
, Они в принципе похожи на свои "первый" и "последний" аналоги, но потенциально совпадающие элементы сильно различаются в зависимости от того, что на самом деле находится на странице.
Но сначала немного теории. Помните, что простые селекторы являются независимыми условиями. Они остаются независимыми даже при объединении в составные селекторы. Это означает, что p
ни под влиянием, ни под влиянием того, как :nth-child()
или же :nth-of-type()
Матчи. Объединение их таким образом просто означает, что элементы должны соответствовать всем их условиям одновременно, чтобы соответствовать.
Здесь вещи становятся интересными. Это независимое сопоставление означает, что я могу проявить изобретательность в том, как я выражаю составные (и сложные) селекторы в терминах простого английского языка, не меняя значения селекторов. На самом деле, я могу сделать это прямо сейчас так, чтобы разница между :nth-child(2)
а также :nth-of-type(2)
кажется настолько значительным, что псевдоклассы также могут быть совершенно не связаны друг с другом (во всяком случае, за исключением части "братьев и сестер"):
p:nth-child(2)
: Выберите второго ребенка среди своих братьев и сестер, если и только если этоp
элемент.p:nth-of-type(2)
: Выберите второйp
элемент среди своих братьев и сестер.
Внезапно они звучат по-другому! И здесь немного пояснений.
Любой элемент может иметь только один дочерний элемент, соответствующий :nth-child(X)
для любого целого числа X одновременно. Вот почему я решил подчеркнуть "второго ребенка", упомянув его первым. Кроме того, этот дочерний элемент будет соответствовать только p:nth-child(X)
если это будет иметь тип p
(помните, что "тип" относится к тэгу). Это очень соответствует :first-child
а также :last-child
(и, аналогично, p:first-child
а также p:last-child
).
Есть два аспекта :nth-of-type(X)
с другой стороны:
Потому что "тип" в
:nth-of-type()
это то же понятие, что и "тип" в селекторе типов, это семейство псевдоклассов предназначено для использования в сочетании с селекторами типов (даже если они все еще работают независимо). Вот почемуp:nth-of-type(2)
может быть выражено так же кратко, как "Выберите второйp
элемент среди своих братьев и сестер."Это просто работает!Однако в отличие от
:first-of-type
а также:last-of-type
X требует, чтобы в родительском элементе действительно было столько дочерних элементов одного и того же типа. Например, если есть только одинp
элемент внутри своего родителя,p:nth-of-type(2)
ничего не будет соответствовать внутри этого родителя, даже если этоp
элемент гарантированно совпадаетp:first-of-type
а такжеp:last-of-type
(а также, по расширению,p:only-of-type
).
Иллюстрация:
<div class="parent">
<p>Paragraph</p>
<p>Paragraph</p> <!-- [1] p:nth-child(2), p:nth-of-type(2) -->
<p>Paragraph</p>
<footer>Footer</footer>
</div>
<div class="parent">
<header>Header</header>
<p>Paragraph</p> <!-- [2] p:nth-child(2) -->
<p>Paragraph</p> <!-- [3] p:nth-of-type(2) -->
<footer>Footer</footer>
</div>
<div class="parent">
<header>Header</header>
<figure>Figure 1</figure>
<p>Paragraph</p> <!-- [4] -->
<footer>Footer</footer>
</div>
<div class="parent">
<header>Header</header>
<p>Paragraph</p> <!-- [2] p:nth-child(2) -->
<figure>Figure 1</figure>
<hr>
<figure>Figure 2</figure> <!-- [5] .parent > :nth-of-type(2) -->
<p>Paragraph</p> <!-- [5] .parent > :nth-of-type(2) -->
<p>Paragraph</p>
<footer>Footer</footer>
</div>
Что выбрано, что нет, и почему?
Выбранный обоими
p:nth-child(2)
а такжеp:nth-of-type(2)
Первые два потомка этого элемента обаp
элементы, позволяющие этому элементу одновременно сопоставлять оба псевдокласса для одного и того же целочисленного аргумента X, поскольку все эти независимые условия выполняются:- это второй ребенок своего родителя;
- это
p
элемент; а также - это второй
p
элемент в пределах своего родителя.
Выбран
p:nth-child(2)
только
Этот второй ребенокp
элемент, так что это соответствуетp:nth-child(2)
,Но это первый
p
элемент (первый ребенокheader
), так что не совпадаетp:nth-of-type(2)
,Выбран
p:nth-of-type(2)
только
этоp
стихия втораяp
элемент после указанного выше, но это третий дочерний элемент, позволяющий ему соответствоватьp:nth-of-type(2)
но нетp:nth-child(2)
, Помните, опять же, что родительский элемент может иметь только один дочерний элемент, соответствующий:nth-child(X)
для определенного X за один раз - предыдущийp
уже принимает:nth-child(2)
слот в контексте этого конкретного родительского элемента.Не выбран
этоp
Элемент является единственным в своем родителе, и это не его второй дочерний элемент. Поэтому это не соответствует ни:nth-child(2)
ни:nth-of-type(2)
(даже если он не квалифицирован селектором типа; см. ниже).Выбран
.parent > :nth-of-type(2)
Этот элемент является вторым по своему типу в пределах своего родителя. подобно:first-of-type
а также:last-of-type
Отсутствие селектора типа позволяет псевдоклассу потенциально соответствовать более чем одному элементу в пределах одного и того же родителя. В отличие от них, сколько он на самом деле соответствует, зависит от того, сколько на самом деле каждого типа элемента.Здесь есть два
figure
элементы и триp
элементы, позволяющие:nth-of-type(2)
соответствоватьfigure
иp
, Но есть только одинheader
, одинhr
, и одинfooter
, поэтому он не будет соответствовать элементам любого из этих типов.
В заключение, :nth-child()
а также :nth-of-type()
с целочисленным аргументом X (т.е. не в форме An+B с коэффициентом A, равным n), функционирует почти так же, как :first-child
/ :last-child
а также :first-of-type
/ :last-of-type
с основным отличием в том, что аргумент, наряду с самой страницей, влияет на то, сколько разных элементов может быть сопоставлено :nth-of-type()
,
Конечно, есть еще много чего :nth-child()
а также :nth-of-type()
чем просто целочисленный аргумент, но само собой разумеется, что его детали и возможности выходят за рамки этого вопроса.
За p:nth-child(2)
он выбирает второй элемент своего родительского элемента, если это абзац, тогда как p:nth-of-type(2)
выберет второй абзац своего родительского элемента. Если вы все еще в замешательстве, позвольте мне уточнить это для вас. Рассмотрим фрагмент кода ниже:
<section>
<h1>Words</h1>
<p>Little</p>
<p>Piggy</p> <!-- Want this one -->
</section>
Вот, p:nth-child(2)
выберу <p>Little</p>
потому что это второй дочерний элемент своего родителя и элемент абзаца.
Но здесь, p:nth-of-type(2)
выберу <p>Piggy</p>
потому что он выберет второй абзац среди всех абзацев своего родителя.
Помощь от: https://css-tricks.com/the-difference-between-nth-child-and-nth-of-type/
- p:nth-child(1): Означает, что является первым дочерним элементом любого родителя и имеет тип абзаца.
- p: nth-of-type (1): означает, что это первое появление абзаца типа внутри любого родителя
p:nth-child(2){background:#f00;}
p:nth-of-type(2){background:#0f0;}
<div>
<div>first child</div>
<p>second child and first element of class "p"</p>
<p>third child and second element of class "p"</p>
<p>fourth child and third element of class "p"</p>
</div>
Другие ответы подчеркнули основное различие между обоими селекторами, которое заключается в том, что nth-child
будет рассматривать все элементы внутри одного контейнера (элементы одного уровня) и nth-of-type
рассмотрим все элементы одного типа внутри одного контейнера.
:nth-child(an+b)
нотация псевдокласса представляет элемент, у которого есть родственники +b-1 перед ним в дереве документа.
:nth-of-type(an+b)
нотация псевдокласса представляет элемент, у которого есть родные элементы +b-1 с тем же расширенным именем элемента перед ним в дереве документа ref.
Из этого мы можем добавить еще одно важное различие между обоими селекторами, которое заключается в том, что nth-of-type
обычно используется с селектором тега, тогда как nth-child
не нужен селектор тегов. Другими словами, nth-of-type
Можно выбрать более одного элемента, но nth-child
Можно выбрать только один элемент. Добавление селектора тегов с nth-of-type
ограничит выбор одним элементом и добавит селектор тега nth-child
просто добавит больше ограничений к одному целевому элементу. 1
п-й ребенок ()
Этот селектор выберет второго ребенка .container
,
.container :nth-child(2) {
border:1px solid red;
}
<div class="container">
<p>aaa</p>
<p>aaa</p>
<h1>title</h1>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<h1>title</h1>
</div>
Это тот же селектор, что и выше, но мы добавляем ограничение тега: Найти второго потомка .container
если это p
тег, затем выберите его.
.container p:nth-child(2) {
border:1px solid red;
}
<div class="container">
<p>aaa</p>
<p>aaa</p>
<h1>title</h1>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<h1>title</h1>
</div>
Если мы изменим p
с h1
ничего не будет выбрано, потому что второй ребенок не является h1
:
.container h1:nth-child(2) {
border:1px solid red;
}
<div class="container">
<p>aaa</p>
<p>aaa</p>
<h1>title</h1>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<h1>title</h1>
</div>
п-оф-типа ()
Этот селектор выберет 2-й p
и 2-й h1
, nth-of-type
будет вести себя как nth-child
после группировки элементов по одному типу.
.container :nth-of-type(2) {
border:1px solid red;
}
<div class="container">
<p>aaa</p>
<p>aaa</p>
<h1>title</h1>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<h1>title</h1>
</div>
Таким образом, мы выбираем второго ребенка внутри этого:
<div class="container">
<p>aaa</p>
<p>aaa</p> <-- this one -->
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
</div>
Тогда второй ребенок внутри этого:
<div class="container">
<h1>title</h1>
<h1>title</h1> <-- this one -->
</div>
Добавление селектора тега просто ограничит выбор только одной группой элементов:
.container p:nth-of-type(2) {
border:1px solid red;
}
.container h1:nth-of-type(2) {
border:1px solid green;
}
<div class="container">
<p>aaa</p>
<p>aaa</p>
<h1>title</h1>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<h1>title</h1>
</div>
Если ваш контейнер содержит только один тип элемента, оба селектора наверняка дадут один и тот же результат, но не будут вести себя одинаково (т. Е. Последующее изменение логики будет другим). Вы также можете заметить, что если вы удалите селектор тегов из обоих, вы также получите тот же результат:
.container :nth-of-type(2) {
border:1px solid red;
}
.container :nth-child(2) {
color:red;
}
/* The below will also select the same
.container p:nth-child(2)
.container p:nth-of-type(2)
.container *:nth-child(2)
.container *:nth-of-type(2)
*/
<div class="container">
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
</div>
Другим отличием (это личная мысль) может быть производительность обоих. nth-child
может быть быстрее, так как он учитывает все элементы одного уровня, так что у нас будет один цикл для проверки всех элементов. nth-of-type
Нужно рассматривать элементы разных типов не одновременно, поэтому, вероятно, у нас будет больше обработки, поэтому она будет медленнее (это мой собственный вывод, основанный на том, как работают оба. У меня нет формальных доказательств этого).
1: я рассматриваю выделение внутри одного контейнера, используя целое число в nth-child/nth-of-type.
Предположим, у нас есть следующий HTML:
<div id="content">
<p>a1</p>
<span>a2</span>
<p>a3</p>
<span>a4</span>
</div>
1) #content p:nth-child(2)
- относится к 0 элементам
так как p:nth-child(2)
требует, чтобы это был второй ребенок и что тег p
, но на самом деле тег является <span>
,
2) #content *:nth-child(2)
- яблоки для <span>a2</span>
так как *:nth-child(2)
Требуется только, чтобы он был вторым дочерним элементом, а не требовать имя тега. *
может быть любым именем тега.
3) #content p:nth-of-type(2)
, -- относится к <p>a3</p>
так как p:nth-of-type(2)
означает второй в <p>
список узлов.
4) #content *:nth-of-type(2)
, -- относится к <p>a3</p>
а также <span>a4</span>
так как *:nth-of-type(2)
требуется только второй в том же списке узлов тегов.
p:nth-child
"Селектор" в "Простом английском" означает выбрать элемент, если:
- Это элемент абзаца
- Это второй дочерний элемент родителя (если второй дочерний элемент родителя не
<p>
CSS не повлияет)
p:nth-of-type
Селектор в "Простом английском" означает:
- Выберите второй абзац
<p>
ребенок родителя (забота о<p>
Перечислите всех детей<p>
и возьми)
.first p:nth-child(2) {
background: blue // this css not effect
}
.first p:nth-of-type(2) {
background: red
}
<div class="first">
<p>This is 1st paragraph</p>
<div>This is a div</div>
<p>This is 2nd paragraph</p>
</div>
Как говорит MDN:
CSS-псевдокласс : nth-child () сопоставляет элементы на основе их положения в группе братьев и сестер.
Это означает, что p:nth-child(2)
будет только захватывать <p>
элементы, которые являются вторым дочерним элементом своего родителя.
Тем не мение, p:nth-of-type(2)
будет захватывать <p>
элементы, которые являются вторым элементом их родителя, независимо от индекса элемента. Это означает, что элемент может иметь 100 дочерних элементов, и если последний дочерний элемент является вторым элементом абзаца среди его родных элементов, на него будут влиять перечисленные стили.
Некоторые вещи, которые нужно иметь в виду (это еще не было сказано):
элемент
nth-child(1)
а такжеnth-of-type(1)
Это всегда правда.
элемент
nth-child(2)
а такжеnth-of-type(2)
Это верно, когда первые 2 дочерних элемента имеют одинаковый тип.
элемент
nth-child(3)
а такжеnth-of-type(2)
Это верно, когда 1-й и 3-й дочерние элементы одного и того же типа, а 2-й дочерний - нет.
элемент
nth-child(2)
а такжеnth-of-type(3)
Это всегда ложь, так как элемент, который является третьим по своему типу, не может быть вторым потомком своего родителя.
Пример:
p:nth-child(2) { color: red; }
p:nth-of-type(2) { background-color: yellow; }
<div>
<p>Paragraph 1</p> <!-- p:nth-child(1), p:nth-of-type(1) -->
<p>Paragraph 2</p> <!-- p:nth-child(2), p:nth-of-type(2) -->
<span></span>
</div>
<hr />
<div>
<p>Paragraph 1</p> <!-- p:nth-child(1), p:nth-of-type(1) -->
<span></span>
<p>Paragraph 2</p> <!-- p:nth-child(3), p:nth-of-type(2) -->
</div>
Браузер в этом коде: p:nth-child(2)
не видит p
и вызовите его родителя, а затем выберите 2
nd дочерний элемент. Браузер просто хочет выбрать второго дочернего элемента p
родитель.
Но в этом коде: p:nth-of-type(2)
, Браузер перейдет на второй p
элемент. вызовите его родителя, а затем выберите2
nd p
элемент.
Вы можете увидеть это в следующем коде:
<div>
<span>some text</span>
<p>first P element</p> <!-- p:nth-child(2) -->
<p>second P element</p> <!-- p:nth-of-type(2) -->
</div>
p:nth-child(2)
: Это выберет все <p>
элементы, которые являются вторым элементом внутри их родительского элемента. Первым элементом может быть любой другой элемент. например
<div>
<h1>Title</h1>
<p>Paragraph</p> ** p:nth-child(2)
<p>Paragraph</p>
</div>
<div>
<p>Paragraph</p>
<p>Paragraph</p> ** p:nth-child(2)
<p>Paragraph</p>
</div>
<div>
<p>Paragraph</p>
<h1>Text</h1>
<p>Paragraph</p> ** None are selected
</div>
p:nth-of-type(2)
: Это выберет все <p>
элементы, которые являются вторым появлением <p>
элемент внутри их родительского элемента.
<div>
<h1>Title</h1>
<p>Paragraph</p>
<p>Paragraph</p> ** p:nth-of-type(2)
</div>
<div>
<h1>Title</h1>
<h2>Subtitle</h2>
<p>Paragraph</p>
<h2>Subtitle</h2>
<h2>Subtitle</h2>
<h2>Subtitle</h2>
<p>Paragraph</p> ** p:nth-of-type(2)
</div>
<div>
<h1>Title</h1>
<p>Paragraph</p> ** None are selected
</div>