28172 sujets

CSS et mise en forme, CSS3

Bonjour,

j'aimerai comprendre précisément la différence entre les pseudo classes :last-child et :last-of-type

Je viens de perdre une heure pour une mise en page en trois colonnes. J'ai un div conteneur avec un display:table qui contient trois paragraphes avec un display:table-cell. J'ai appliqué un border-right:dashed 1px; sur les paragraphes pour créer une ligne de séparation et j'ai passé une heure à essayer de comprendre pourquoi ça ne fonctionne pas pour retirer le border du dernier paragraphe qui est donc sur la bordure du site avant de voir que ça fonctionne avec :last-of-type.

Il n'y a pas d'explications claires sur les spécificités de ces pseudo classes sur w3schools, dans les deux cas il donne pour exemple une couleur de background et ne disent rien de plus.

http://www.w3schools.com/cssref/sel_last-of-type.asp
http://www.w3schools.com/cssref/sel_last-child.asp

Je pense qu'il doit y avoir une question d'ordre d'application des styles dans les enfants du div mais je n'ai pas capté précisément le principe.


<!DOCTYPE html>
<head>

<style>
#table { width:1000px; height:300px; display:table; }
.colonne { width:333px; height:300px; display:table-cell; border-right:dashed 1px gray }
.colonne:last-of-type{ border-right:none; }
</style>

</head>
<body>

<div id="table">
<p class="colonne">blablabla</p>
<p class="colonne">blablabla</p>
<p class="colonne">blablabla</p>
</div>

</body>
</html>

Modifié par Cyberdome (12 Oct 2016 - 23:24)
Bonjour.

:last-child, :nth-child, :first-child ne fonctionnent qu'avec des éléments successifs de même type, par exemple des li dans une ol ou une ul. Ainsi, dans ce cas, la présence d'un élément autre que des li et de même niveau dans une ul ou une ol, par exemple, un p rendra inopérantes ces pseudo-classes pour les éléments li placés à la suite de l'élément p.

Par contre, les pseudo classes: first-of-type, :nth-of-type, :last-of-type (et autres) peuvent cibler des éléments d'un type donné placés après des éléments d'un autre type, quel que soit le nombre de ces derniers.

Il est donc préférable, pour des raisons de simplicité, d’utiliser dans tous les cas les pseudo-classes :first-of-type, :nth-of-type, :last-of-type (et autres) plutôt que les first-child, last-child, nth-child(et autres).

Plus sur les (immenses) possibilités de ces pseudo-classes :

http://nthmaster.com/

Ceci dit, a priori, je ne vois pas pourquoi ton code initial ne fonctionnerait pas, à moins que :last-child doive se placer après l'élément et avant la classe.

Ceci dit, il y a moyen de simplifier ton code HTML :

<!DOCTYPE html>
<head>
<style>
#table { width:1000px; height:300px; display:table; }
#table p { width:333px; height:300px; display:table-cell; border-right:dashed 1px gray }
#table p:last-of-type { border-right:none; }
</style>
</head>

<body>
<div id="table">
<p>blablabla</p>
<p>blablabla</p>
<p>blablabla</p>
</div>
</body>
</html>


Enfin, je m'interroge sur l'opportunité d'utiliser un id plutôt qu'une classe pour un élément éventuellement susceptible d'être reproduit en plusieurs exemplaires.

Bonne continuation.
Modifié par thierry (09 Oct 2016 - 14:51)
Administrateur
Hello,

Un exemple simple :

<div>
  <p></p>
  <h1></h1>
  <p></p>
  <p></p>
</div>


p:nth-child(2) -> ne renvoie rien car le 2è enfant de div n'est pas un p
p:nth-of-type(2) -> renvoie le 2è p, donc le 3è enfant
Administrateur
thierry a écrit :
:last-child, :nth-child, :first-child ne fonctionnent qu'avec des éléments successifs de même type, par exemple des li dans une ol ou une ul. Ainsi, dans ce cas, la présence d'un élément autre que des li et de même niveau dans une ul ou une ol, par exemple, un p rendra inopérantes ces pseudo-classes pour les éléments li placés à la suite de l'élément p.

En fait, à vrai dire :last-child, :nth-child, :first-child fonctionnent aussi très bien lorsque les éléments ne sont pas de même type.

Par exemple (même si la syntaxe n'est pas valide) :
<ul>
  <li></li>
  <p></p>
  <li></li>
  <li></li>
</ul>


:nth-child(3) renvoie le 3è élément (c'est le 2è li)
p:first-child ne renvoie rien car le 1er enfant n'est pas un p
p:nth-child(3) ne renvoie personne car le 3è élément n'est pas un p
p:nth-child(2) renvoie le 2è élément (car c'est un p)
p:nth-of-type(1) (ou p:first-of-type) renvoie le 1er (et unique) p
p:nth-of-type(2) ne renvoie rien car il n'y a qu'un seul enfant de type p
Modifié par Raphael (09 Oct 2016 - 14:41)
Administrateur
Cyberdome a écrit :

.colonne:last-of-type{ border-right:none; }

Attention car cette syntaxe est trompeuse : "type" ne peut cibler qu'un type d'élément, pas une classe.

En clair, ici il ne va pas chercher "le dernier élément de classe .colonne", mais bel est bien "le dernier élément du type concerné par la classe colonne", or ce type est <p>. C'est donc le p qui est cherché et non les éléments de classe .colonne.
a écrit :
En fait, à vrai dire :last-child, :nth-child, :first-child fonctionnent aussi très bien lorsque les éléments ne sont pas de même type.

Par exemple (même si la syntaxe n'est pas valide) :

<ul>
<li></li>
<p></p>
<li></li>
<li></li>
</ul>

:nth-child(3) renvoie le 3è élément (c'est le 2è li)
p:first-child ne renvoie rien car le 1er enfant n'est pas un p
p:nth-child(3) ne renvoie personne car le 3è élément n'est pas un p
p:nth-child(2) renvoie le 2è élément (car c'est un p)
p:nth-of-type(1) (ou p:first-of-type) renvoie le 1er (et unique) p
p:nth-of-type(2) ne renvoie rien car il n'y a qu'un seul enfant de type p

Cool ! Merci, Raphaël !
Modifié par thierry (09 Oct 2016 - 14:55)
Je viens de tester sur jsfiddle.net et toute les solutions fonctionnent y compris avec .colonne:last-child !!

Enfin merci pour vos explications, je reste sur votre solution qui passe partout et qui est plus simple Smiley smile

Je suis étonné que ca fonctionne sur jsfiddle alors que ça ne fonctionne ni sur chrome ni sur waterfox, je ne sais pas comment ces sites fonctionnent mais pour le coup celui ci n'est pas fiable.

Je vais prendre l'habitude d'utiliser :last-of-type plutôt que :last-child