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?

Miral
la source

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.

VoteyDisciple
la source
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
25
Pour info, IE 9 prend en charge:last-child .
Jari Keinänen
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.

Branden Silva
la source
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

Tarik
la source
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;
}
ccpizza
la source
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]-->
nzifnab
la source
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.

lexx
la source
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.

ecollis6
la source
0

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

#refundReasonMenu #nav ul
{
    border-bottom: 1px solid #b5b5b5;
}
côtelette de porc
la source
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>
Ozzy
la source
-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;
}
changelog
la source