Jouons avec les pseudos-classes des sélecteurs css

Ç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 :

~ Bee Vibrant ~ 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. Sunny Side Up Tantum autem cuique tribuendum, primum quantum ipse efficere possis, deinde etiam quantum ille quem diligas atque adiuves, sustinere. Little stars 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. Campo de Amapolas 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.