La Cascade

Un peu de tout sur CSS, HTML, SVG et JS,traduit du web anglophone
Rechercher

Pseudo-éléments :before & :after

par Louis Lazaris, 5 avril 2014, css, pseudo-elements, accessibilite, article original paru le 13 juillet 2011 dans Smashing Magazine

Cet article de Louis Lazaris s'adresse à ceux qui ont découvert avec émerveillement les trucs sympas qu'on peut faire avec les pseudo-éléments et veulent mieux connaître cette technique très utilisée. On commence par :before et :after.


Cet article s'adresse à ceux qui ont découvert les trucs cools qu'on peut faire avec les pseudo-éléments et veulent mieux connaître cette technique. La spécification CSS contient d'autres pseudo-éléments, mais je me concentrerai ici sur :before et :after et pour la simplicité je parlerai de "pseudo-éléments" en me référant spécifiquement à ces deux-là. ( NdT : pour plus d'infos sur les pseudo-éléments et pseudo-classes, vous pouvez consulter cet article et pour une plongée en profondeur sur :before et :after cet autre article ici-même).

Que fait un pseudo-élément ?

Il fait exactement ce que son nom implique : il crée un élément factice et l'insère avant ou après le contenu de l'élément que vous avez ciblé.

Un pseudo-élément ne change rien dans le document lui-même, en fait il insère des éléments "fantômes" qui sont visibles par l'utilisateur et auxquels on peut appliquer un style CSS.

Syntaxe basique

Les pseudo-éléments :before et :after sont très simples à coder, en voici un exemple :

#exemple:before {
   content: "#";
}

#exemple:after {
   content: ".";
}

Il y a deux choses à noter à propos de cet exemple. D'abord, nous ciblons ici le même élément en utilisant #exemple:before et #exemple:after. À proprement parler, ce sont les pseudo-éléments dans ce code.

Ensuite, sans la propriété content , les pseudo-éléments ne servent à rien. Si le sélecteur pseudo-élément est nécessaire pour cibler l'élément, il n'est pas pour autant suffisant, vous n'insérerez rien tant que vous n'aurez pas ajouté la propriété content.

Dans l'exemple que nous venons de voir, on insère un symbole # avant le contenu de l'élément ayant l'id exemple et un point après.

À propos de la syntaxe

Vous pourriez tout aussi bien laisser la propriété content vide et traiter le pseudo-élément comme une boîte vide :

#example:before {
   content: "";
   display: block;
   width: 100px;
   height: 100px;
}

Toutefois, vous ne pouvez pas supprimer la propriété content, le pseudo-élément ne fonctionnerait pas. A minima, la propriété content doit contenir des "" vides.

Vous avez peut-être remarqué qu'on peut aussi utiliser la syntaxe ::before et ::after. Pour faire bref, il n'y a pas de différence entre les deux syntaxes, c'est juste une façon de différencier les pseudo-éléments et les pseudo-classes en CSS3 mais vous pouvez oublier cette syntaxe.

Caractéristiques du contenu inséré

Comme déjà mentionné, le contenu inséré n'est pas visible dans les sources de la page (si vous cherchez sur DevTools), il n'est visible que dans le CSS.

De plus, l'élément inséré est par défaut un élément inline. Pour lui donner une hauteur, un padding, des marges, etc, vous devrez le définir explicitement comme un élément block.

Cela nous amène à une brève description de la façon d'appliquer un style à nos pseudo-éléments. Regardons ce graphique tiré de mon éditeur de texte :

display, width, height sont les styles qui affectent le pseudo élément

Dans cet exemple, j'ai surligné les styles qui seront appliqués aux éléments insérés avant et après le contenu de l'élément cible. Les pseudo-éléments ont ceci d'unique qu'on insère le contenu et le style dans le même bloc de déclaration.

Notez également que les règles d'héritage CSS s'appliquent aux éléments insérés. Si par exemple vous avez défini une police de caractères Helvetica, Arial, sans-serif pour l'élément body de votre document, le pseudo-élément héritera de cette police comme n'importe quel autre élément.

De la même façon, les pseudo-éléments n'héritent pas de styles qui ne sont pas naturellement hérités de leurs parents, tels que les paddings et les marges.

Avant ou après quoi ?

Notre intuition nous dit que le contenu sera inséré avant et après l'élément cible. Mais comme je l'ai déjà suggéré, ce n'est pas le cas.

Le contenu injecté sera un enfant de l'élément cible, mais il sera placé "avant" ou "après" tout autre contenu dans cet élément.

Pour mieux comprendre, prenons un exemple. Tout d'abord le HTML :

<p class="box">Other content.</p>

Et maintenant le CSS qui insère le pseudo-élément :

p.box {
   width: 300px;
   border: solid 1px white;
   padding: 20px;
}

p.box:before {
   content: "#";
   border: solid 1px white;
   padding: 2px;
   margin: 0 10px 0 0;
}

Dans le HTML, tout ce qu'on voit est un paragraphe avec une classe box, et les mots "Other content" à l'intérieur (c'est ce que vous verriez si vous inspectiez la source). Dans le CSS, le paragraphe a une largeur, un padding et une bordure visible.

Puis nous avons le pseudo-élément. Il insère un symbole # "avant" le contenu du paragraphe. Le CSS qui suit lui donne une bordure, un padding, des marges.

Et voici le résultat dans notre navigateur :

symbole inséré avant le paragraphe, le symbole comporte une bordure, un padding et des marges

La boîte extérieure est notre paragraphe. La bordure qui entoure le symbole # représente les limites de notre pseudo-élément. Autrement dit, celui-ci n'est pas inséré "avant" le paragraphe, il est placé avant "Other content" à l'intérieur du paragraphe.

Insérer du contenu non-textuel

Nous avons vu que nous pouvions donner à la propriété content une valeur textuelle - y compris éventuellement une chaîne de caractères vide (""). Mais nous avons encore deux options possibles.

Tout d'abord, nous pouvons inclure une URL qui pointe vers une image, exactement comme nous le ferions pour inclure une image de background dans le CSS :

p:before {
   content: url(image.jpg);
}

Remarquez qu'il n'y a pas de guillemets. Si c'était le cas, cela deviendrait une chaîne de caractères et on insèrerait le texte "url(image.jpg)" comme contenu au lieu d'insérer l'image elle-même.

Bien entendu, nous pouvons inclure une Data URI à la place de la référence de l'image, tout comme pour un background CSS.

Nous avons également la possibilité d'inclure une fonction sous la forme attr(X). Selon les termes de la spécification, "cette fonction retourne sous forme de chaîne de caractères la valeur de l'attribut X pour le sujet du sélecteur".

Par exemple :

a:after {
   content: attr(href);
}

Que fait cette fonction attr() ? Elle prend la valeur de l'attribut spécifié (href) et la retourne sous forme de texte, qui sera inséré par le pseudo-élément.

Le code ci-dessus aura pour effet d'afficher sur la page la valeur de href de chaque élément <a> et de le placer immédiatement après chaque élément <a>. Un cas d'usage classique concerne la feuille de style "impression", puisque cela permet d'inscrire en clair l'URL après chaque lien sur les documents imprimés.

Nous pourrions aussi utiliser cette fonction pour aller chercher la valeur de l'attribut title d'un élément, ou même les valeurs des microdonnées. Toutefois, s'il serait pratique d'aller chercher le title ou le texte alt d'une image pour l'afficher sur la page avec un pseudo-élément, ce n'est pas possible. Rappelez-vous que le pseudo-élément doit être un enfant de l'élément auquel il est appliqué. Les images, qui sont des éléments vides (void elements), n'ont pas l'éléments enfants, par conséquent cela ne marche pas. Même chose pour tous les éléments vides, tels que <input> (NdT : à part ces deux là, les autres ne sont pas très intéressants).

Accessibilité

Les pseudo-éléments, on l'a vu, n'apparaissent pas dans le DOM, ils ne sont pas réels. De ce fait, les appareils ou logiciels d'assistance pour les personnes ayant des déficiences ne peuvent pas y accéder. Veillez à ne pas utiliser de pseudo-éléments pour générer un contenu indispensable à l'usabilité ou à l'accessibilité de vos pages.

Ressources intéressantes sur :before et :after

A Single Div, des exemples d'illustrations réalisées à partir d'une simple div et de CSS utilisant :before et :after, très impressionnant !

Autres ressources externes

Articles de Louis Lazaris traduits dans La Cascade

Voir la page de Louis Lazaris et la liste de ses articles dans La Cascade.
Article original paru le 13 juillet 2011 dans Smashing Magazine
Traduit avec l'aimable autorisation de Smashing Magazine et de Louis Lazaris.
Copyright Smashing Magazine © 2011