Sélecteur CSS pour le premier élément avec classe

j'ai un tas d'éléments avec un nom de classe red , mais je ne semble pas pouvoir sélectionner le premier élément avec le class="red" en utilisant la règle CSS suivante:

.red:first-child {
    border: 5px solid red;
}
<p class="red"></p>
<div class="red"></div>

Qu'est-ce qui ne va pas dans ce sélecteur et comment le corriger?

Merci pour les commentaires, j'ai compris que l'élément est le premier enfant de son parent d'être sélectionné, ce qui n'est pas le cas que j'ai. J'ai la structure suivante, et cette règle échoue comme indiqué dans les commentaires:

.home .red:first-child {
    border: 1px solid red;
}
<div class="home">
    <span>blah</span>
    <p class="red">first</p>
    <p class="red">second</p>
    <p class="red">third</p>
    <p class="red">fourth</p>
</div>

Comment puis-je cibler le premier enfant avec la classe red ?

727
demandé sur TylerH 2010-04-27 02:51:13

18 réponses

C'est l'un des exemples les plus connus d'auteurs qui ne comprennent pas comment :first-child fonctionne. introduit dans CSS2 , le :first-child pseudo-classe représente le tout premier enfant de son parent . C'est tout. Il y a une idée fausse très répandue selon laquelle il détecte n'importe quel élément enfant qui est le premier à correspondre aux conditions spécifiées par le reste du sélecteur composé. En raison de la façon dont les sélecteurs fonctionnent (voir ici) pour une explication), c'est tout simplement pas vrai.

sélecteurs de niveau 3 introduit une :first-of-type pseudo-classe , qui représente le premier élément parmi les frères et sœurs de son type d'élément. Cette réponse explique, avec des illustrations, la différence entre :first-child et :first-of-type . Cependant , comme pour :first-child , il ne tient pas compte d'autres conditions ou attributs. En HTML, le type d'élément est représenté par le nom de la balise. Dans la question, ce type est p .

malheureusement, il n'y a pas de pseudo-classe similaire :first-of-class pour correspondre au premier élément enfant d'une classe donnée. Une solution que Lea Verou et je suis venu avec pour cela (bien que totalement indépendamment) est d'abord appliquer vos styles désirés à tous vos éléments avec cette classe:

/* 
 * Select all .red children of .home, including the first one,
 * and give them a border.
 */
.home > .red {
    border: 1px solid red;
}

... puis "annuler" les styles pour les éléments avec la classe que viennent après le premier , en utilisant le combinateur de frère général ~ dans une règle prépondérante:

/* 
 * Select all but the first .red child of .home,
 * and remove the border from the previous rule.
 */
.home > .red ~ .red {
    border: none;
}

Maintenant, seul le premier élément avec class="red" aura une bordure.

Voici une illustration de la façon dont les règles sont appliquées:

<div class="home">
  <span>blah</span>         <!-- [1] -->
  <p class="red">first</p>  <!-- [2] -->
  <p class="red">second</p> <!-- [3] -->
  <p class="red">third</p>  <!-- [3] -->
  <p class="red">fourth</p> <!-- [3] -->
</div>
  1. pas de règles sont appliquées; aucune frontière est rendu.

    Cet élément n'a pas la classe red , c'est donc ignorée.

  2. Seule la première règle est appliquée; une bordure rouge est rendu.

    Cet élément a la classe red , mais il n'est précédé d'aucun élément de la classe red dans sa parent. Ainsi, la deuxième règle n'est pas appliquée, seule la première, et l'élément qui garde sa frontière.

  3. les deux règles sont appliquées; aucune frontière n'est rendue.

    Cet élément appartient à la classe red . Il est également précédé d'au moins un autre élément de la classe red . Ainsi, les deux règles sont appliquées, et la deuxième déclaration border l'emporte sur la première, la" défaisant " pour ainsi dire.

comme un bonus, bien qu'il ait été introduit dans les sélecteurs 3, le combinateur frère général est en fait assez bien-soutenu par IE7 et plus récent, contrairement à :first-of-type et :nth-of-type() qui sont seulement soutenus par IE9 à partir. Si vous avez besoin d'un bon navigateur, vous avez de la chance.

en fait, le fait que le combinateur frère est le seul élément important dans cette technique, et il a un tel support de navigateur étonnant, rend cette technique très polyvalent - vous pouvez l'adapter pour filtrer des éléments par d'autres choses, en plus des sélecteurs de classe:

  • vous pouvez utiliser ceci pour travailler autour de :first-of-type dans IE7 et IE8, en fournissant simplement un sélecteur de type au lieu d'un sélecteur de classe (encore une fois, plus sur son usage incorrect ici dans une section ultérieure):

    article > p {
        /* Apply styles to article > p:first-of-type, which may or may not be :first-child */
    }
    
    article > p ~ p {
        /* Undo the above styles for every subsequent article > p */
    }
    
  • vous pouvez filtrer par attribut selectors ou tout autre des sélecteurs simples au lieu de classes.

  • vous pouvez également combiner cette technique prépondérante avec pseudo-éléments même si les pseudo-éléments ne sont techniquement pas de simples sélecteurs.

notez que pour que cela fonctionne, vous aurez besoin de savoir à l'avance quels seront les styles par défaut pour vos autres éléments frères pour que vous puissiez outrepasser la première règle. Outre, puisque cela implique des règles de dépassement dans CSS, vous ne pouvez pas obtenir la même chose avec un seul sélecteur pour l'utilisation avec les sélecteurs API , ou Selenium CSS locators.

il est intéressant de mentionner que les sélecteurs 4 introduit une extension de la :nth-child() notation (à l'origine une toute nouvelle pseudo-classe appelée :nth-match() ), qui vous permettra d'utiliser quelque chose comme :nth-child(1 of .red) lieu d'un hypothétique .red:first-of-class . Comme il s'agit d'une proposition relativement récente, il n'y a pas encore assez d'applications interopérables pour qu'elle puisse être utilisée sur les sites de production. Espérons que cela changera bientôt. En attendant, la solution que j'ai suggérée devrait fonctionner dans la plupart des cas.

gardez à l'esprit que cette réponse suppose que la question est à la recherche de chaque premier élément enfant qui a une classe donnée. Il n'y a pas de pseudo-classe ni même de solution CSS générique pour la correspondance nième d'un sélecteur complexe dans tout le document - si une solution existe dépend fortement de la structure du document. jQuery fournit :eq() , :first , :last et plus à cet effet, mais notez encore que ils fonctionnent très différemment de :nth-child() et al . En utilisant L'API Selecteurs, vous pouvez utiliser document.querySelector() pour obtenir la toute première correspondance:

var first = document.querySelector('.home > .red');

ou utilisez document.querySelectorAll() avec un indexeur pour choisir une correspondance spécifique:

var redElements = document.querySelectorAll('.home > .red');
var first = redElements[0];
var second = redElements[1];
// etc

bien que la solution .red:nth-of-type(1) dans la réponse originale acceptée par Philip Daubmeier œuvres (qui a été écrit à l'origine par Martyn mais supprimé depuis), il ne se comporte pas de la manière que vous attendez qu'il.

par exemple, si vous vouliez seulement sélectionner le p dans votre markup original:

<p class="red"></p>
<div class="red"></div>

... alors vous ne pouvez pas utiliser .red:first-of-type (équivalent de .red:nth-of-type(1) ), parce que chaque élément est le premier (et seul) de son type ( p et div respectivement), donc les deux seront appariés par le sélecteur.

Lorsque le premier élément d'une certaine classe est aussi le premier de son type , la pseudo-classe travail, mais ce se produit seulement par coïncidence . Ce comportement est démontré dans la réponse de Philip. Au moment où vous enfoncez un élément du même type avant cet élément, le sélecteur va tomber en panne. Prenant le balisage mis à jour:

<div class="home">
  <span>blah</span>
  <p class="red">first</p>
  <p class="red">second</p>
  <p class="red">third</p>
  <p class="red">fourth</p>
</div>

L'application D'une règle avec .red:first-of-type fonctionnera, mais une fois que vous ajoutez un autre p sans la classe:

<div class="home">
  <span>blah</span>
  <p>dummy</p>
  <p class="red">first</p>
  <p class="red">second</p>
  <p class="red">third</p>
  <p class="red">fourth</p>
</div>

... le sélecteur va immédiatement tomber en panne, parce que le premier élément .red est maintenant le deuxième p élément.

1181
répondu BoltClock 2017-06-29 10:56:18

le sélecteur :first-child est destiné, comme son nom l'indique, à sélectionner le premier enfant d'une étiquette parent. Les enfants doivent être intégrés dans la même étiquette parentale. Votre exemple exact fonctionnera (vient de l'essayer ici ):

<body>
    <p class="red">first</p>
    <div class="red">second</div>
</body>

peut-être avez-vous imbriqué vos étiquettes dans différentes étiquettes de parent? Est-ce que vos étiquettes de classe red sont vraiment les premières étiquettes sous le parent?

noter aussi que ce n'est pas seulement s'appliquent à la première étiquette de ce genre dans le document entier, mais chaque fois qu'un nouveau parent est enroulé autour de lui, comme:

<div>
    <p class="red">first</p>
    <div class="red">second</div>
</div>
<div>
    <p class="red">third</p>
    <div class="red">fourth</div>
</div>

first et third seront rouges alors.

mise à jour:

Je ne sais pas pourquoi martyn a supprimé sa réponse, mais il avait la solution, le sélecteur :nth-of-type :

<html>
<head>
<style type="text/css">
.red:nth-of-type(1)
{
    border:5px solid red;
} 
</style>
</head>

<body>
    <div class="home">
        <span>blah</span>
        <p class="red">first</p>
        <p class="red">second</p>
        <p class="red">third</p>
        <p class="red">fourth</p>
    </div>
</body>
</html>

Crédits Martyn . Pour plus d'infos exemple ici . Soyez conscient qu'il s'agit d'un sélecteur CSS 3, donc tous les navigateurs ne le reconnaîtront pas (par exemple IE8 ou plus ancien).

305
répondu Philip Daubmeier 2017-05-23 12:34:54

la bonne réponse est:

.red:first-child, :not(.red) + .red { border:5px solid red }

partie I: si element est le premier par rapport à son parent et a la classe "rouge", il doit obtenir border.

Partie II: si ".l'élément rouge" n'est pas le premier à son parent, mais suit immédiatement un élément sans classe ".rouge", il est aussi méritent l'honneur de ladite frontière.

Violon ou il n'est pas arrivé.

réponse de Philip Daubmeier, tandis que accepté, n'est pas correcte - voir ci-joint le violon.

La réponse de BoltClock fonctionnerait, mais définit et écriteau inutilement les styles

(en particulier une question où il hériterait autrement une frontière différente - vous ne voulez pas déclarer autre à la frontière:aucun)

EDIT: Dans le cas où vous avez "rouge" suivant non-Rouge plusieurs fois, chaque "premier" rouge obtiendra la bordure. Pour éviter cela, il faudrait utiliser le Boltclock's réponse. Voir violon

59
répondu SamGoody 2016-11-15 13:26:22

vous pouvez utiliser first-of-type ou nth-of-type(1)

.red {
  color: green;  
}

/* .red:nth-of-type(1) */
.red:first-of-type {
  color: red;  
}
<div class="home">
  <span>blah</span>
  <p class="red">first</p>
  <p class="red">second</p>
  <p class="red">third</p>
  <p class="red">fourth</p>
</div>
13
répondu Moes 2017-01-13 00:57:44

Pour assortir votre sélection, l'élément doit avoir un nom de classe red et doit être le premier enfant de son parent.

<div>
    <span class="red"> <!-- MATCH -->
</div>

<div>
    <span>Blah</span>
    <p class="red"> <!-- NO MATCH -->
</div>

<div>
    <span>Blah</span>
    <div><p class="red"></div> <!-- MATCH -->
</div>
8
répondu Chetan Sastry 2011-12-16 18:50:41

puisque les autres réponses couvrent ce qui est faux avec elle, je vais essayer l'autre moitié, comment la réparer. Malheureusement, je ne sais pas que vous avez un CSS seulement solution ici, au moins pas que je peux penser à . Il ya quelques autres options....

  1. Assignez une classe first à l'élément lorsque vous le générez, comme ceci:

    <p class="red first"></p>
    <div class="red"></div>
    

    CSS:

    .first.red {
      border:5px solid red;
    }
    

    ce CSS ne correspond qu'aux éléments des classes à la fois first et red .

  2. alternativement, faites la même chose en JavaScript, par exemple voici ce que jQuery vous utiliseriez pour faire ceci, en utilisant le même CSS que ci-dessus:

    $(".red:first").addClass("first");
    
7
répondu Nick Craver 2012-06-25 23:07:00

selon votre problème mis à jour

<div class="home">
  <span>blah</span>
  <p class="red">first</p>
  <p class="red">second</p>
  <p class="red">third</p>
  <p class="red">fourth</p>
</div>

Que diriez-vous de

.home span + .red{
      border:1px solid red;
    }

Ce sera sélectionnez classe d'accueil , l'élément span et, enfin, tous les .les éléments rouges qui sont placés immédiatement après les éléments de portée.

référence: http://www.w3schools.com/cssref/css_selectors.asp

5
répondu StinkyCat 2014-01-21 11:49:39

vous pouvez changer votre code à quelque chose comme ça pour le faire fonctionner

<div class="home">
  <span>blah</span>
  <p class="red">first</p>
  <p class="red">second</p>
  <p class="red">third</p>
  <p class="red">fourth</p>
</div>

Cela fait le travail pour vous

.home span + .red{
      border:3px solid green;
    }

Voici une référence CSS de SnoopCode à ce sujet.

3
répondu Prabhakar 2015-10-14 10:15:28

j'utilise ci-dessous CSS pour avoir une image de fond pour la liste ul li

#footer .module:nth-of-type(1)>.menu>li:nth-of-type(1){
  background-position: center;
  background-image: url(http://monagentvoyagessuperprix.j3.voyagesendirect.com/images/stories/images_monagentvoyagessuperprix/layout/icon-home.png);
  background-repeat: no-repeat;
}
<footer id="footer">
  <div class="module">
    <ul class="menu ">
      <li class="level1 item308 active current"></li>
      <li> </li>
    </ul> 
  </div>
  <div class="module">
    <ul class="menu "><li></li>
      <li></li> 
    </ul>
  </div>
  <div class="module">
    <ul class="menu ">
      <li></li>
      <li></li>
    </ul>
  </div>
</footer>
3
répondu li bing zhao 2018-06-18 15:10:14

vous pouvez utiliser nth-of-type(1) mais assurez-vous que le site n'a pas besoin de soutenir IE7 etc, Si c'est le cas, utilisez jQuery pour ajouter la classe de corps puis trouver l'élément via IE7 la classe de corps puis le nom de l'élément, puis Ajouter dans le style nth-child à elle.

2
répondu Jamie Paterson 2013-06-03 12:59:17

essayez ceci:

    .class_name > *:first-child {
        border: 1px solid red;
    }
2
répondu Loy 2016-08-04 22:06:52

j'ai eu celui-ci dans mon projet.

div > .b ~ .b:not(:first-child) {
	background: none;
}
div > .b {
    background: red;
}
<div>
      <p class="a">The first paragraph.</p>
      <p class="a">The second paragraph.</p>
      <p class="b">The third paragraph.</p>
      <p class="b">The fourth paragraph.</p>
  </div>
2
répondu Yener Örer 2018-01-31 07:02:47

Les réponses ci-dessus sont trop complexes.

.class:first-of-type { }

sélectionnez le premier type de classe. source MDN

2
répondu Gabriel Fair 2018-06-28 13:53:43

pour une raison ou une autre, aucune des réponses ci-dessus ne semblait aborder le cas de the real first et only first child du parent.

#element_id > .class_name:first-child

toutes les réponses ci-dessus échoueront si vous voulez appliquer le style seulement à l'enfant de première classe dans ce code.

<aside id="element_id">
  Content
  <div class="class_name">First content that need to be styled</div>
  <div class="class_name">
    Second content that don't need to be styled
    <div>
      <div>
        <div class="class_name">deep content - no style</div>
        <div class="class_name">deep content - no style</div>
        <div>
          <div class="class_name">deep content - no style</div>
        </div>
      </div>
    </div>
  </div>
</aside>
1
répondu Yavor Ivanov 2018-06-18 15:08:56

essayez ce Simple et efficace

 .home > span + .red{
      border:1px solid red;
    }
0
répondu Friend 2016-07-26 08:19:19

essayez cette solution:

 .home p:first-of-type {
  border:5px solid red;
  width:100%;
  display:block;
}
<div class="home">
  <span>blah</span>
  <p class="red">first</p>
  <p class="red">second</p>
  <p class="red">third</p>
  <p class="red">fourth</p>
</div>

CodePen lien

0
répondu Santosh Khalse 2018-06-18 15:08:35

N'est nécessaire qu'en premier et un seul paragraphe devient rouge. Comment?

<!DOCTYPE html><html><head><style>

article p:nth-child(1){background: red}
article p:first-child{background: red}

</style></head><body>

<p style="color:blue">Needed only first and only one paragraph had red. How?</p>

<article>
<p>The first paragraph.</p>
<div><p>The second paragraph.</p></div>
<p>The third paragraph.</p>
<div><p>The fourth paragraph.</p></div>
</article>

</body></html>
0
répondu Alexander V. Ulyanov 2018-07-15 17:48:05

je pense que l'utilisation du sélecteur relatif + pour sélectionner les éléments placés immédiatement après, fonctionne ici le mieux (comme peu suggéré avant).

Il est également possible pour ce cas d'utiliser ce sélecteur

.home p:first-of-type

mais c'est le sélecteur d'éléments pas la classe un.

Voici une belle liste de sélecteurs CSS: https://kolosek.com/css-selectors/

-1
répondu Nesha Zoric 2018-04-11 06:47:01