Les sélecteurs CSS
Les sélecteurs
Le sélecteur est la partie qui va permettre de pointer vers l’élément de la page sur lequel la règle va devoir s’appliquer, et là repose toute la stratégie et l’optimisation des feuilles de style. En effet, bien souvent on tombe dans la facilité et on a facilement recours à l’ajout de classe, ou d’identifiant sur les balises, afin de mieux les cibler… Il en résulte, que l’on tombe vite dans une classite aigüe, et inutile. De plus, cette éventuelle surcharge HTML, n’a aucune relation directe avec le contenu, et donc, interfère avec la réelle logique de séparation de contenu / affichage. À y regarder de plus près, bien comprendre les sélecteurs, sera également un atout et un gage d’optimisation, si on utilise la librairie jQuery.
Il peut être composé de un ou plusieurs éléments, et être eux-même de différentes natures ;
- de type balise, en indiquant le nom de la balise qui doit être affectée, (
p
,body
,h1
…) - de type classe, en indiquant la classe qui doit être affectée. Dans un fichier CSS, toutes les classes doivent être précédées d’un point (
.classe
,.entete
…) - de type identifiant, en indiquant l’id qui doit être affectée. Dans un fichier CSS, tous les identifiants doivent être précédés d’un dièse (
#liste
,#maincontent
…)
Chacun de ces ciblages peut être cumulés et composés. Cumulés veut dire qu’il est possible d’enchaîner plusieurs instruction (h1 strong
, section p em
… ) et composés signifie que l’on peut mélanger les diverses natures de sélecteurs (p.special
, #maincontent article .notes
, …).
p strong
, cible tous les éléments <strong> contenu dans une balise <p>#maincontent article .notes
, cible toutes les classes notes contenues dans une balise<article>
elle-même contenue dans une balise ayant pour identifiantmaincontent
,
Seulement il faut faire attention, car en fonction de l’ordre, ou de la présence d’un espace, la signification peut être complètement différente. En effet, les trois exemples ci-dessous sont totalement différents ;
p.special
, indique tous les éléments<p>
qui sont de classe .special, donc par exemple<p class="special">
p .special
, indique tous les éléments<p>
qui contiennent un élément de classe .special, donc par exemple<p><strong class="special">
.special p
, indique tous les éléments de classe .special qui contiennent un élément<p>
, donc par exemple<article class="special"><p>
Il existe également des opérateurs, (caractères spécifiques), qui permettent de lier les éléments entre eux d’une certaine manière, afin de représenter diverses relations, (descendance, contenances, non contenances, etc…) ;
p > em
, qui indique que l’élément<em>
doit être immédiatement enfant de l’élément<p>
, ce qui est complètement différent du sélecteurp em
, qui indique que cela cible tous les éléments<em>
contenu dans un élément<p>
. Par exemple,<p><em>
est valide, alors que<p><strong><em>
ne l’est pas.p + p
, indique que cela cible tous les éléments<p>
, déjà précédé d’un élément<p>
. Par exemple,<ul></ul><p>
n’est pas concerné, alors que<p></p><p>
l’est. Bien sur, le sélecteurul + p
, donnerait l’exemple inverse.
Bien entendu, l’ensemble de ces possibilités peut toujours être combiné, nature des sélecteurs et opérateurs (.special > p
, #maincontant + footer
…), et cumulés (p.special > .note strong
…) … ce qui donne déjà un grand nombre de possibilités et d’affinage. Mais les possibilités ne s’arrêtent pas là. Il existe un grand nombre de pseudos classes et pseudos éléments qui viennent compléter la liste et étendre encore les possibilités.
Il nous arrive parfois de rencontrer, sur des projets existants, des sélecteurs particuliers, ou bien d’en chercher un qui soit le mieux adapté. Afin d’affiner notre requête, il est intéressant de se rapprocher d’un outil tel que SelectORacle pour décrypter le jargon, ou de puiser de l’inspiration dans les tableaux du w3c avec Selectors – Level 3 et Selectors – Level 4.
Les pseudos
Les pseudos sont des outils qui permettent de sélectionner certaines parties de l’arborescence du DOM. Les pseudos classes sont des états particuliers d’un élément, (:hover
, :focus
, :target, nth-child(n)
, :empty
, :root
…), alors que les pseudos éléments sont des aspects d’un ou plusieurs éléments, qui ne sont pas directement représentés ou marqués, dans l’arborescence du document (::first-letter
, ::first-line
, ::before
, ::selection
…).
La distinction entre les deux vient du fait de l’usage d’un simple double point (: pour les pseudos classes) et de deux double points (:: pour les pseudos éléments). Attention, si par le passé, les pseudos éléments pouvaient aussi bien être écrits, avec un simple, comme avec deux double points, certaines nouvelles instructions, comme ::selection
par exemple, nécessitent les deux double points. Donc autant utiliser la bonne syntaxe pour l’ensemble des pseudos éléments.
Certaines classes, comme nth-child(Arg)
ou nth-of-type(Arg)
, peuvent ouvrir vers un argument Arg
. Cet argument est parfois sous-employé, ou mal estimé. Prenons quelques instants pour en observer quelques mécaniques. Il est possible de le rencontrer sous deux formes principales : soit avec un seul paramètre du type x
, ou x
qui est représenté aussi bien par un nombre entier que par une chaîne de caractères parmi even
ou odd
, soit accompagné d’un second paramètre, généralement sous la forme d’un nombre et de la lettre n
, ce qui donne par exemple 2n + x
, qu’en est-il au juste ?
x
, pointe vers la xème instance de l’élément… donc la valeur3
indique la 3ème instance et uniquement la troisième instance, la valeureven
affecte tous les éléments pair (en partant du premier), et la valeurodd
tous les éléments impairs,n + x
, pointe toujours vers la xème instance de l’élément, mais cette fois-ci, on ré-applique la règle toutes lesn
instances de l’élément… donc2n + 2
, affecte tous les éléments 1 sur 2, en partant du 2ème… dans ce cas-là cela équivaut à event,3n + 2
, affecte tous les éléments 1 sur 3 en partant du second,n - x
, fonctionne de la même manière que pour la particularité précédente, donc6n - 2
, affecte tous les éléments 1 sur 6 en partant du -2ème, éléments, donc cela commencera au 4ème…n + x
oun - x
, une autre approche pour ces deux dernières particularités pourrait être de poser l’équation suivante :(n * 0) + x
(n * 1) + x
(n * 2) + x
- …
-n + x
, cette fois-ci n n’aura pas de valeur numéraire associée, mais le signe-
, qui affectera donc les x premiers éléments, par exemple-n + 3
affecte les 3 premiers éléments,
nth-child(), nth-of-type()
Les deux pseudos classes, :nth-child()
et :nth-of-type()
, fonctionnent à l’identique au niveau des paramètres qu’elles reçoivent, à la différence que la première instruction considère tous les enfants de la balise parent (afin de définir l’ordre calculé) alors que la seconde ne prend en compte que les éléments du type recherché. Par exemple, dans le fragment HTML suivant, p:nth-child(2)
affecte le premier paragraphe (Lorem ipsum dolor…), <h1>
est pris en compte comme enfant de la balise parent, alors qu’avec p:nth-of-type(2)
cela affecte le second paragraphe (In commodo et odio…), <h1>
n’est pas pris en compte pour compter les instances;
<article> <h1>Titre</h1> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p> <p>In commodo et odio vitae varius.</p> <p>Suspendisse tincidunt sed dui sed suscipit.</p> </article>
En complément de :nth-child()
et :nth-of-type()
, il existe les deux instructions inverses, :nth-last-child()
et :nth-last-of-type()
qui fonctionnent à l’identique, à ceci près que le décompte s’effectue à partir des derniers éléments, et non des premiers. Attention, Internet Explorer ne prend en compte toutes ces pseudos classes que depuis sa version 9 !
before et after !
Les pseudos éléments ::before
et ::after
, ont la particularité de pouvoir ajouter du contenu à un élément tout en le stylant, par exemple ;
.euro li::after { content: "€"; color: rgba(238,243,49,0.68); }
ou également pour le contournement de l’ajout d’un élément, inutile en HTML, afin de jouer le rôle de clear:both
;
<ul> <li>Element</li> <li>Element</li> </ul> li { float:left } ul::after { content:""; display:block; clear:both }
sans oublier que ces deux pseudos éléments peuvent se coupler avec des instructions fonctions, qui vont par exemple nous permettre de compter des itérations count()
; Prenons un simple fragment HTML de liste et ajoutons le code CSS ci-dessous. Lors du ciblage de l’élément <ul>
le compteur réinitialise la variable listeElement
. Cette variable s’incrémente à chaque élément <li>
, et grâce au pseudo élément ::before
il est possible de placer du contenu devant l’élément <li>
résultant de la concaténation de chaînes de caractères, avec la variable listeElement
;
ul { counter-reset:listeElement; } ul li { counter-increment:listeElement; } ul li:before { content: "T - " counter(listeElement) " " }
Les sélecteurs d’attributs
Il est également possible de sélectionner les éléments par la présence, et également la valeur des attributs qu’il contient. Le choix et les possibilités, sont nombreuses, et la prise en compte des navigateurs assez large (hors Internet Explorer 6). La première instruction, ci-dessous, va simplement vérifier la présence d’un attribut pour pouvoir cibler, ou non, un élément ;
element[attribut]
L’utilisation est simple, et la syntaxe intuitive. La requête, entre crochet, peut se compléter d’expressions afin d’affiner la recherche, et d’aller beaucoup plus loin que la simple présence de l’attribut ;
element[attribut="valeur"]
, non seulement l’attribut doit être présent, mais il doit en plus être strictement égal à la valeur indiquée, par exemple<element class="valeur et autre">
ne sera pas ciblé, et pour assurer une meilleure portabilité il est préférable d’user des double quote autour de la valeur,element[attribut*="valeur"]
, l’attribut doit contenir la chaîne de caractères recherchée, peu importe où; par exemple<element class="contientvaleurdanslemot">
sera ciblé,element[attribut^="valeur"]
, l’attribut doit commencer par la valeur spécifiée, par exemple<element class="contient valeur">
ne sera pas ciblé, alors que<element class="valeur contient">
le sera,element[attribut$="valeur"]
, l’attribut doit se terminer par la valeur, avec ou sans espace… ce qui rend cette instruction très utile pour cibler les formats de fichier, par exemplea[href$=".pdf"]
ciblera tous les liens vers des fichiers PDF,element[attribut~="valeur"]
, recherche une valeur entière, par exemple<element class="contient valeur dans lemot">
sera ciblé, alors que<element class="contientvaleurdanslemot">
ne le sera pas,element[attribut|="valeur"]
, recherche une valeur séparée par un trait d’union, par exemple<element class="contient-valeur-dans-le-mot">
sera ciblé,element[attributA]
[attributA]
, recherche à multiple critères, bien sûr chacun de ces critères peut prendre toutes les valeurs vues jusqu’ici.
L’instruction peut également être utilisée soit de manière générale, soit de manière anonyme, ce qui revient au même ;
*[attribut] [attribut]
A la recherche des sélecteurs oubliés
Nous connaissons tous les principaux types de sélecteurs qui gravitent dans la panoplie du parfait webmaster, mais qu’en est-il des sélecteurs avancés de CSS3, des sélecteurs d’attributs ou encore des nouvelles vagues de niveau 4 ? Je vous propose que nous prenions quelques instants pour en explorer quelques-uns (ou bien revenir dessus, si vous les utilisez déjà). Que nous les utilisions pour optimiser nos CSS ou pour affiner nos requêtes jQuery, il est toujours bon de les garder en sous-mains lors de nos développements.
Deux tableaux et un site sont constamment nécessaires à portée de souris et les trois se passent de commentaires… Selectors sur w3c qui couvre les niveaux 1, 2 et 3, Selectors Level 4 version éditeur qui présente les nouvelles propositions, et enfin, The Skinny on CSS Attribute Selectors où Chris Coyier, dans un style visuel très ergonomique, nous remémore les divers sélecteurs d’attributs…