Ça fait quelques temps (depuis la sortie de firefox 3.5, en fait) que j’avais envie de jouer avec quelques sélecteurs css issus de la version 3 de la norme. En fait, nous allons nous amuser avec quelques pseudos-classes. Pour les cancres, les pseudos-classes sont un mécanisme de css qui permet de sélectionner des éléments selon des critères qui ne sont pas explicitements contenus dans de document.
a:hover { … } /* Ça vous dit quelque chose ? */
Voici donc notre élément html de travail, un joli (ou pas) tableau tout ce qu’il y a de plus classique :
| riri | fifi | loulou |
| moutarde | mayo | ketchup |
| git | cvs | svn |
| linus | richard | eric |
| html | css | php |
| symfony | cake | pluf |
Et le code associé :
<table> <tr> <td>riri</td> <td>fifi</td> <td>loulou</td> </tr> <tr> <td>moutarde</td> <td>mayo</td> <td>ketchup</td> </tr> <tr> <td>git</td> <td>cvs</td> <td>svn</td> </tr> <tr> <td>linus</td> <td>richard</td> <td>eric</td> </tr> <tr> <td>html</td> <td>css</td> <td>php</td> </tr> <tr> <td>symfony</td> <td>cake</td> <td>pluf</td> </tr> </table>
nth-child et nth-last-child
Notre premier sélecteur porte le doux nom de nth-child. Son utilité ? Il permet de styler des éléments choisis selon leur index dans des groupes. Un exemple sera beaucoup plus parlant.
Imaginons que je veuille affecter une couleur de fond à toutes les lignes impaires de mon tableau (ce que est un besoin assez courant). Et pour pousser le vice, je souhaite aussi mettre en gras une ligne sur trois à partir de la deuxième (ça, c’est déjè moins courant).
Et bien surprise, je vais faire ça très simplement :
table tr:nth-child(2n+1) { background-color: #f0f0f0; } table tr:nth-child(3n+2) { font-weight: bold; }
La syntaxe « nth-child(an+b) » signifie qu’on sélectionne l’élément numéro « b » dans chaque groupe de « a » éléments par rapport à un parent commun. Quand au sélecteur nth-last-child, il fonctionne exactement de la même façon, excepté le fait que le comptage des éléments se fait de bas en haut dans le document (c’est clair ?).
Et le résultat :
| riri | fifi | loulou |
| moutarde | mayo | ketchup |
| git | cvs | svn |
| linus | richard | eric |
| html | css | php |
| symfony | cake | pluf |
Pas mal, non ? Comment, vous ne voyez pas la différence ? Et bien, c’est parce que votre navigateur ne gère pas les sélecteurs avancés. Il serait peut-être temps d’utiliser un vrai navigateur ?
Ici, nous avons pris un tableau pour exemple, mais on pourrait styler un commentaire sur deux dans un blog, ou imaginer des choses beaucoup plus tordues. Par exemple, on pourait affecter 5 couleurs successives à tous les paragraphes de la page :
p:nth-child(5n+1) { background-color: blue; } p:nth-child(5n+2) { background-color: red; } p:nth-child(5n+3) { background-color: yellow; } /* … */
Ah ! Et au fait :
tr:nth-child(2n+1) /* peut être raccourci en */ tr:nth-child(odd) /* et */ tr:nth-child(2n) /* est équivalent à */ tr:nth-child(even)
nth-of-type, nth-last-of-type
Le sélecteur nth-of-type ressemble à nth-child, sauf qu’on ne prends en compte que les éléments de même type pour effectuer les groupes. Quand à nth-last-of-type, vous aurez deviné à quoi il sert. Là encore, un exemple sera plus parlant.
Admettons que mon article contienne des images d’illustrations. Je veux aligner successivement les images à droite, puis à gauche, et ce automatiquement, dans la mesure où je suis un fainéant.
#article img:nth-of-type(odd) { float: right; } #article img:nth-of-type(even) { float: left; }
Et le résultat :

Primi igitur omnium statuuntur Epigonus et Eusebius ob nominum gentilitatem oppressi. praediximus enim Montium sub ipso vivendi termino his vocabulis appellatos fabricarum culpasse tribunos ut adminicula futurae molitioni pollicitos.

Tantum autem cuique tribuendum, primum quantum ipse efficere possis, deinde etiam quantum ille quem diligas atque adiuves, sustinere.

Non enim neque tu possis, quamvis excellas, omnes tuos ad honores amplissimos perducere, ut Scipio P. Rupilium potuit consulem efficere, fratrem eius L. non potuit. Quod si etiam possis quidvis deferre ad alterum, videndum est tamen, quid ille possit sustinere.

Post hanc adclinis Libano monti Phoenice, regio plena gratiarum et venustatis, urbibus decorata magnis et pulchris ; in quibus amoenitate celebritateque nominum Tyros excellit, Sidon et Berytus isdemque pares Emissa et Damascus saeculis condita priscis.
Alors !? Hein ?! C’est-y-pas beau ?!? Moi, en tout cas, ça m’émerveille toujours autant (oui, je suis sensible).
first-child et last-child
Ça, c’est facile. first-child permet de sélectionner le premier parmi une liste d’éléments. Et last-child, je vous laisse deviner ce que c’est.
Petit exemple facile :
table tr:first-child, table tr:last-child { background-color: #f0f0f0; }
Et que voit-on apparaitre devant nos yeux ébahis ???
| riri | fifi | loulou | loulou |
| moutarde | mayo | ketchup | loulou |
| git | cvs | svn | loulou |
| linus | richard | eric | loulou |
| html | css | php | loulou |
| symfony | cake | pluf | loulou |
first-of-type, last-of-type
Les sélecteurs first-of-type et last-of-type permettent respectivement de sélectionner le premier et le dernier parmi les frères de l’élément. Comme d’hab’ un petit exemple :
td:first-of-type { padding-left: 100px ; } td:last-of-type { padding-right: 100px; }
Ici, nous sélectionnons les premiers et derniers éléments « td » de chaque ligne et on leur applique un padding particulier. Le résultat :
| riri | fifi | loulou | loulou |
| moutarde | mayo | ketchup | loulou |
| git | cvs | svn | loulou |
| linus | richard | eric | loulou |
| html | css | php | loulou |
| symfony | cake | pluf | loulou |
| symfony | cake | pluf | loulou |
only-child, only-of-type
Le sélecteur only-child désigne un élément qui n’as pas de frères dans l’arbo. only-of-type désigne un élément qui n’a pas de frères du même type que lui.
<ul> <li>test</li> <li>test</li> <li>test</li> <li>test</li> </ul> <ul> <li>test</li> </ul> <ul> <li>test</li> <li>test</li> </ul>
li:only-of-type { font-weight: bold; background-color: lime; }
- test
- test
- test
- test
- test
- test
- test
not
not(X) permet de sélectionner les éléments qui ne correspondent pas au sélecteur passé en paramètre.
li:not(:only-of-type) { font-weight: bold; background-color: lime; }
- test
- test
- test
- test
- test
- test
- test
Conclusions et références
Bien entendu, tous les sélecteurs peuvent dans une certaine mesure être combinés pour créer des expressions puissantes (tordues). Autre évidence, l’intérêt de la chose reste somme toutes assez limités à cause du support navrant des sélecteurs css3 de la part d’un certain navigateur.
Pour finir, pour les curieux, je vous dirige vers les références qui ont servi de base à cet article.
6 Commentaires
Salut,
Je connaissais les pseudo-classes mais j’ai appris des choses ! Bon article !
De mon côté, j’utilise Firefox3 et l’exemple avec les images float:right / float:left ne marche pas.
Comme tu le soulignais c’est dommage que ces pseudos-classes qui facilitent vraiment la vie ne soient pas compatibles avec tous les navigateurs… Encore et toujours ce pb de rétro-compatibilité :/
En tous cas, merci pour ce post intéressant. Je ne connaissais pas ton blog, encore une bonne découverte !
@ bientôt
Effectivement, ça fonctionne sur la page de l’article, mais pas sur la page d’accueil. La faute à wordpress qui fout sa zone dans le html de l’article.
Merci pour l’article très bien expliqué. J’avais du mal avec certains concepts mais maintenant c’est clair.
Un jour faut prendre une décision et la mienne c’est : tant pis pour ceux qui ont un vieux navigateur.
ces selecteurs vont bien me servir pour mon theme de mon blog Wp (pour bien aligner les images en .wp-caption )
Je ne savais pas qu’on pouvait utiliser des syntaxe complexe comme 2n+1, par contre je connaissais odd et even qui sont plus facile à retenir.
Bonjour,
Merci pour l’article.
Ces sélecteurs peuvent être utilisé dès maintenant avec le plugin selectivizr.
Merci pour cet article.
Après l’avoir suivi sucrupuleusement je n’avais pas obtenu tout à fait le même résultat : les bordures des cases apparaissaient encore. Problème résolu grâce à l’attribut border-collapse de table :
table {
border-collapse:collapse ;
}