Utilisation du sélecteur du dernier enfant


106

Mon objectif est d'appliquer le CSS sur le dernier li, mais il ne le fait pas.

#refundReasonMenu #nav li:last-child {
    border-bottom: 1px solid #b5b5b5;
}
<div id="refundReasonMenu">
    	<ul id="nav">
    		<li><a id="abc" href="#">abcde</a></li>
    		<li><a id="def" href="#">xyz</a></li>
    	</ul>
    </div>

Comment puis-je sélectionner uniquement le dernier enfant?

Réponses:


171

La :last-childpseudoclasse ne peut toujours pas être utilisée de manière fiable sur les navigateurs. En particulier, les versions d'Internet Explorer <9 et Safari <3.2 ne le prennent certainement pas en charge , bien qu'Internet Explorer 7 et Safari 3.2 le prennent en charge :first-child, curieusement.

Votre meilleur pari est d'ajouter explicitement une last-childclasse (ou similaire) à cet élément et de l'appliquer à la li.last-childplace.


46
IE8 ne prend pas en charge non :last-childplus. Et ce n'est pas si curieux. :first-childest une pseudo-classe CSS2, :last-childune pseudo-classe CSS3.
mercator

92
last-child fonctionne dans tous les navigateurs modernes, ce qui signifie bien sûr qu'il ne fonctionne dans aucune version d'IE.
Rob


6
@mercator C'est curieux que: first-child ait été implémenté dans CSS2 mais: last-child a été laissé jusqu'à CSS3 ... semble assez évident de les ajouter en même temps.
Cobby

21
IE7 refuse de reconnaître d'autres enfants bâtards
Dewayne

76

Une autre solution qui pourrait fonctionner pour vous est d'inverser la relation. Vous définiriez donc la bordure de tous les éléments de la liste. Vous utiliseriez alors first-child pour éliminer la bordure du premier élément. Le premier enfant est pris en charge statiquement dans tous les navigateurs (ce qui signifie qu'il ne peut pas être ajouté dynamiquement via un autre code, mais le premier enfant est un sélecteur CSS2, alors que le dernier enfant a été ajouté dans la spécification CSS3)

Remarque: cela ne fonctionne comme vous le souhaitez que si vous n'avez que 2 éléments dans la liste comme votre exemple. Tout 3e élément et sur aura des bordures appliquées à eux.


2
+1 pour penser hors de la boîte :-) Je viens de convertir mes éléments last-child en first-child et changé par border-right en border-left pour les séparateurs de menu. Maintenant, IE8 aime mon css.
Scott B

43

Si vous pensez que vous pouvez utiliser Javascript, alors depuis le support de jQuery last-child, vous pouvez utiliser la méthode css de jQuery et la bonne chose qu'elle supportera presque tous les navigateurs

Exemple de code:

$(function(){
   $("#nav li:last-child").css("border-bottom","1px solid #b5b5b5")
})

Vous pouvez trouver plus d'informations ici: http://api.jquery.com/css/#css2


8
Parlez de sale.
md1337

95
Wayyy mieux de faire quelque chose comme $("#nav li:last-child").addClass('last-child')pour que vous puissiez garder votre style dans vos feuilles de style.
jason

C'est plus propre que la première solution car elle est gérée automatiquement. Mais je suis aussi d'accord avec Jason.
Josh M.

1
En fait, IE7 ne charge pas une classe qui a à la fois div:last-childet div.last-child. Il semble qu'il considère la :last-childsyntaxe comme invalide et toute classe avec ce pseudo-sélecteur ne sera pas appliquée.
Josh M.

@Josh M.: C'est un comportement correct et attendu. Très malheureux, devrais-je dire. Vous auriez à dupliquer la règle.
BoltClock

19

Si le nombre d'éléments de la liste est fixe, vous pouvez utiliser le sélecteur adjacent, par exemple si vous n'avez que trois <li>éléments, vous pouvez sélectionner le dernier <li>avec:

#nav li+li+li {
    border-bottom: 1px solid #b5b5b5;
}

3
Votre sélecteur est faux. li + #nav lisélectionne l' liintérieur #navqui vient après li. Votre sélecteur devrait simplement être #nav li + li + li.
BoltClock

1
C'est chouette. Fonctionne bien dans IE8, mais pas dans IE7.
Mateng

13

Si vous avez souvent besoin de sélecteurs CSS3, vous pouvez toujours utiliser la bibliothèque selectivizr sur votre site:

http://selectivizr.com/

C'est un script JS qui ajoute la prise en charge de presque tous les sélecteurs CSS3 aux navigateurs qui ne les prendraient pas autrement en charge.

Jetez-le dans votre <head>tag avec une condition IE:

<!--[if (gte IE 6)&(lte IE 8)]>
  <script src="/js/selectivizr-min.js" type="text/javascript"></script>
<![endif]-->


0

Au lieu d'utiliser une classe, vous pouvez utiliser une liste détaillée, en définissant les éléments enfants dt pour avoir un style et les éléments enfants dd pour en avoir un autre. Votre exemple deviendrait:

#refundReasonMenu #nav li:dd
{
  border-bottom: 1px solid #b5b5b5;
}

html:

<div id="refundReasonMenu">
  <dl id="nav">
        <dt><a id="abc" href="#">abcde</a></dt>
        <dd><a id="def" href="#">xyz</a></dd>
  </dl>
</div>

Aucune des deux méthodes n'est meilleure que l'autre et c'est simplement une question de préférence personnelle.


0

Une autre façon de le faire consiste à utiliser le sélecteur de dernier enfant dans jQuery, puis à utiliser la méthode .css (). Soyez fatigué car certaines personnes sont encore à l'âge de pierre en utilisant des navigateurs JavaScript désactivés.


0

Pourquoi ne pas appliquer la bordure au bas de l'UL?

#refundReasonMenu #nav ul
{
    border-bottom: 1px solid #b5b5b5;
}

1
Si vous avez padding-bottomsur l' <ul>élément ou margin-bottomsur le dernier <li>élément, cela n'aura pas le placement souhaité de droite sous le dernier <li>élément. Sinon, c'est une bonne solution.
Wex

0

Si vous faites flotter les éléments, vous pouvez inverser l'ordre

c'est float: right;à dire au lieu defloat: left;

Et puis utilisez cette méthode pour sélectionner le premier enfant d'une classe.

/* 1: Apply style to ALL instances */
#header .some-class {
  padding-right: 0;
}
/* 2: Remove style from ALL instances except FIRST instance */
#header .some-class~.some-class {
  padding-right: 20px;
}

Cela applique en fait la classe à la LAST instance uniquement parce qu'elle est maintenant dans l'ordre inverse.

Voici un exemple de travail pour vous:

<!doctype html>
<head><title>CSS Test</title>
<style type="text/css">
.some-class { margin: 0; padding: 0 20px; list-style-type: square; }
.lfloat { float: left; display: block; }
.rfloat { float: right; display: block; }
/* apply style to last instance only */
#header .some-class {
  border: 1px solid red;
  padding-right: 0;
}
#header .some-class~.some-class {
  border: 0;
  padding-right: 20px;
}
</style>
</head>
<body>
<div id="header">
  <img src="some_image" title="Logo" class="lfloat no-border"/>
  <ul class="some-class rfloat">
    <li>List 1-1</li>
    <li>List 1-2</li>
    <li>List 1-3</li>
  </ul>
  <ul class="some-class rfloat">
    <li>List 2-1</li>
    <li>List 2-2</li>
    <li>List 2-3</li>
  </ul>
  <ul class="some-class rfloat">
    <li>List 3-1</li>
    <li>List 3-2</li>
    <li>List 3-3</li>
  </ul>
  <img src="some_other_img" title="Icon" class="rfloat no-border"/>
</div>
</body>
</html>

-2

C'est difficile à dire sans voir le reste de votre CSS, mais essayez d'ajouter !importantdevant la couleur de la bordure, pour en faire comme ceci:

#refundReasonMenu #nav li:last-child
{
  border-bottom: 1px solid #b5b5b5 !important;
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.