146 votes

Puis-je combiner :nth-child() ou :nth-of-type() avec un sélecteur arbitraire ?

Existe-t-il un moyen de sélectionner tous les nièmes enfants ? qui correspond (ou ne correspond pas) à un sélecteur arbitraire ? Par exemple, je veux sélectionner toutes les lignes impaires du tableau, mais dans un sous-ensemble de lignes :

table.myClass tr.row:nth-child(odd) {
  ...
}

<table class="myClass">
  <tr>
    <td>Row
  <tr class="row"> <!-- I want this -->
    <td>Row
  <tr class="row">
    <td>Row
  <tr class="row"> <!-- And this -->
    <td>Row
</table>

Mais :nth-child() semble compter tous les tr qu'ils soient ou non de la classe "row", ce qui fait que je me retrouve avec le seul élément même "row" au lieu des deux que je recherche. La même chose se produit avec l'élément :nth-of-type() .

Quelqu'un peut-il expliquer pourquoi ?

169voto

BoltClock Points 249668

Il s'agit d'un problème très courant qui résulte d'une mauvaise compréhension de la manière dont le système d'information est utilisé. :nth-child(An+B) y :nth-of-type() travail.

Dans les sélecteurs de niveau 3, l'option :nth-child() pseudo-classe compte les éléments parmi les tous de leurs frères et sœurs sous le même parent. Il ne compte pas uniquement les frères et sœurs qui correspondent au reste du sélecteur.

De même, le :nth-of-type() pseudo-classe compte les frères et sœurs partageant le même type d'élément, ce qui fait référence au nom de la balise en HTML, et non au reste du sélecteur.

Cela signifie également que si tous les enfants d'un même parent sont du même type d'élément, par exemple dans le cas d'un corps de tableau dont les seuls enfants sont des tr ou un élément de liste dont les seuls enfants sont li éléments, alors :nth-child() y :nth-of-type() se comporteront de manière identique, c'est-à-dire pour chaque valeur de An+B, :nth-child(An+B) y :nth-of-type(An+B) correspondra au même ensemble d'éléments.

En fait, tous les sélecteurs simples d'un sélecteur composé donné, y compris les pseudo-classes telles que :nth-child() y :not() , travail de manière indépendante des uns et des autres, plutôt que de regarder les sous-ensemble d'éléments auxquels correspond le reste du sélecteur.

Cela implique également que il n'y a pas de notion d'ordre entre les sélecteurs simples à l'intérieur de chaque sélecteur composé individuel 1 ce qui signifie, par exemple, que les deux sélecteurs suivants sont équivalents :

table.myClass tr.row:nth-child(odd)
table.myClass tr:nth-child(odd).row

Traduits en anglais, ils signifient tous deux :

Sélectionnez n'importe quel tr qui remplit toutes les conditions indépendantes suivantes :

  • il s'agit d'un enfant impair de son parent ;
  • il appartient à la classe "rangée" ; et
  • il s'agit d'un descendant d'un table qui a la classe "myClass".

(vous remarquerez que j'utilise ici une liste non ordonnée, juste pour enfoncer le clou)

Le niveau 4 des sélecteurs vise à remédier à cette limitation en autorisant :nth-child(An+B of S) 2 pour accepter un argument de sélecteur arbitraire S, toujours en raison de la façon dont les sélecteurs fonctionnent indépendamment les uns des autres dans un sélecteur composé, comme le dicte la syntaxe existante des sélecteurs. Dans votre cas, cela donnerait donc ceci :

table.myClass tr:nth-child(odd of .row)

Bien entendu, comme il s'agit d'une toute nouvelle proposition dans une toute nouvelle spécification, elle ne sera probablement pas mise en œuvre avant le mois d'octobre. dans quelques années .

En attendant, vous devrez utiliser un script pour filtrer les éléments et appliquer des styles ou des noms de classe supplémentaires en conséquence. Par exemple, voici une solution de contournement courante utilisant jQuery (en supposant qu'il n'y ait qu'un seul groupe de lignes peuplé de tr dans le tableau) :

$('table.myClass').each(function() {
  // Note that, confusingly, jQuery's filter pseudos are 0-indexed
  // while CSS :nth-child() is 1-indexed
  $('tr.row:even').addClass('odd');
});

Avec le CSS correspondant :

table.myClass tr.row.odd {
  ...
}

Si vous utilisez des outils de test automatisés tels que Selenium ou des outils de scraping HTML tels que BeautifulSoup, beaucoup de ces outils permettent d'utiliser XPath comme alternative :

//table[contains(concat(' ', @class, ' '), ' myClass ')]//tr[contains(concat(' ', @class, ' '), ' row ')][position() mod 2)=1]

D'autres solutions utilisant des technologies différentes sont laissées à l'appréciation du lecteur ; il ne s'agit ici que d'un exemple bref et artificiel à titre d'illustration.


1 Si vous spécifiez un type ou un sélecteur universel, il doit être placé en premier. Cela ne modifie pas le fonctionnement fondamental des sélecteurs ; il s'agit simplement d'une bizarrerie syntaxique.

2 Il a été proposé à l'origine <code>:nth-match()</code> Cependant, comme il ne compte un élément que par rapport à ses frères et sœurs, et non par rapport à tous les autres éléments qui correspondent au sélecteur donné, il a depuis 2014 été réaffecté en tant qu'extension de l'outil existant <code>:nth-child()</code> au lieu de cela.

8voto

Gaby aka G. Petrioli Points 85891

Pas vraiment.

citation de la documentation

En :nth-child correspond à une pseudo-classe qui possède un élément+b-1 frères et sœurs avant lui dans l'arborescence du document , valeur positive ou nulle de n, et possède un élément parent.

Il s'agit d'un sélecteur à part entière qui ne se combine pas avec les classes. Dans votre règle, il doit simplement satisfaire les deux sélecteurs en même temps, de sorte qu'il affichera l'élément :nth-child(even) s'il s'avère qu'elles ont également la valeur .row classe.

2voto

Gaurav Aggarwal Points 4971

nth-of-type fonctionne en fonction de l'index du même type de l'élément mais nth-child fonctionne uniquement en fonction de l'index, quel que soit le type d'éléments de la fratrie.

Par exemple

<div class="one">...</div>
<div class="two">...</div>
<div class="three">...</div>
<div class="four">...</div>
<div class="five">...</div>
<div class="rest">...</div>
<div class="rest">...</div>
<div class="rest">...</div>
<div class="rest">...</div>
<div class="rest">...</div>

Supposons que dans le code html ci-dessus, nous voulions cacher tous les éléments ayant la classe rest.

Dans ce cas nth-child y nth-of-type fonctionnera exactement de la même manière car tous les éléments sont du même type, c'est-à-dire <div> La css devrait donc être

.rest:nth-child(6), .rest:nth-child(7), .rest:nth-child(8), .rest:nth-child(9), .rest:nth-child(10){
    display:none;
}

O

.rest:nth-of-type(6), .rest:nth-of-type(7), .rest:nth-of-type(8), .rest:nth-of-type(9), .rest:nth-of-type(10){
    display:none;
}

Vous devez maintenant vous demander quelle est la différence entre nth-child y nth-of-type Voici donc la différence

Supposons que le code html soit

<div class="one">...</div>
<div class="two">...</div>
<div class="three">...</div>
<div class="four">...</div>
<div class="five">...</div>
<p class="rest">...</p>
<p class="rest">...</p>
<p class="rest">...</p>
<p class="rest">...</p>
<p class="rest">...</p>

Dans le code html ci-dessus, le type de .rest l'élément est différent des autres .rest sont des paragraphes et d'autres des div, donc dans ce cas, si vous utilisez nth-child il faut écrire comme ceci

.rest:nth-child(6), .rest:nth-child(7), .rest:nth-child(8), .rest:nth-child(9), .rest:nth-child(10){
    display:none;
}

mais si vous utilisez nth-of-type css peut être ceci

.rest:nth-of-type(1), .rest:nth-of-type(2), .rest:nth-of-type(3), .rest:nth-of-type(4), .rest:nth-of-type(5){
    display:none;
}

En tant que type de .rest est <p> donc ici nth-of-type détecte le type de .rest et il a ensuite appliqué des css aux 1er, 2e, 3e, 4e, 5e éléments de <p> .

1voto

the8472 Points 588

Vous pouvez peut-être le faire avec xpath. quelque chose comme //tr[contains(@class, 'row') and position() mod 2 = 0] pourrait fonctionner. D'autres questions relatives à l'OS portent sur les détails de la manière de faire correspondre les classes avec plus de précision.

1voto

Pocketninja Points 172

Voici votre réponse

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>TEST</title>

  <style>

    .block {
      background: #fc0;
      margin-bottom: 10px;
      padding: 10px;
    }
    /* .large > .large-item:nth-of-type(n+5) {
      background: #f00;
    } */

    .large-item ~ .large-item ~ .large-item ~ .large-item ~ .large-item {
      background: #f00;
    }

  </style>
</head>
<body>

<h1>Should be the 6th Hello Block that start red</h1>
<div class="small large">
  <div class="block small-item">Hello block 1</div>
  <div class="block small-item large-item">Hello block 2</div>
  <div class="block small-item large-item">Hello block 3</div>
  <div class="block small-item large-item">Hello block 4</div>
  <div class="block small-item large-item">Hello block 5</div>
  <div class="block small-item large-item">Hello block 6</div>
  <div class="block small-item large-item">Hello block 7</div>
  <div class="block small-item large-item">Hello block 8</div>
</div>

</body>
</html>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X