Une suite d’icônes dans un fichier svg
On a redesigné le site de codeur·euses en Liberté ! C’est vrai que depuis 8 ans, ça commençait à prendre un peu la poussière. C’est un peu plus frais. Il y a encore quelques morceaux en mouvement, n’hésitez pas à nous signaler les petits bugs.
Le plus visible, c’est le nouveau logo 🙀:
Il ressemble à celui d’avant, mais son style reflète bien notre usage des dernières technologies.
C’était aussi l’occasion pour moi de faire un peu de frontend, c’est-à-dire du CSS, du HTML, et du JS1SVG. Voici donc le premier post d’une série de trois, où je raconte les petits hacks, les techniques « modernes », et les bonnes ou mauvaises pratiques découvertes à l’occasion.
Comment faire une suite d’icônes dans un unique fichier svg
Un des chantiers à l’occasion du redesign a été de simplifier la gestion des icônes du site, en permettant de les teinter avec le texte. Il s’agit du problème habituel : une suite de glyphes/symboles/icônes, qu’on veut pouvoir utiliser dans le corps du texte ou dans des boutons.
Je vous livre déjà la conclusion : ne faites pas de polices d’icônes, c’était déjà pénible il y a dix ans, et ça fait longtemps que ça ne sert plus à rien.
Le problème
Avant le redesign, on utilisait déjà une poignée d’icônes, tirée de FontAwesome. Ça ressemblait à ça:
.icon::before {
display: inline-block;
margin-inline-end: 0.5ch;
content: ' '; /* a single unbreakable space */
width: 1.5ch;
background: no-repeat center center;
background-size: contain;
}
.icon-envelope::before { background-image: url('../img/fa-envelope.svg') }
.icon-github::before { background-image: url('../img/fa-github.svg') }
.icon-gitlab::before { background-image: url('../img/fa-gitlab.svg') }
.icon-heart::before { background-image: url('../img/fa-heart.svg') }
.icon-key::before { background-image: url('../img/fa-key.svg') }
.icon-mastodon::before { background-image: url('../img/fa-mastodon.svg') }
.icon-web::before { background-image: url('../img/fa-globe.svg') }
Avec autant de fichiers svg que d’icônes, et autant de règles css à répéter.
Dans le html, ça s’utilisait ainsi :
<p>
Contactez-nous par email à
<a class="icon icon-envelope" href="mailto:bonjour@codeureusesenliberte.fr">bonjour@codeureusesenliberte.fr</a>
</p>
Ça marchait pas mal :
Mais en mode sombre, rien n’allait plus:
Par ailleurs, d’un point de vue accessibilité2, c’était pas génial : il n’y avait pas trace de l’image dans le DOM. On pouvait faire mieux.
Teinter des svg avec la couleur du texte
Faire de la couleur en svg, c’est pas très compliqué, c’est selon le cas l’attribut fill
ou l’attribut stroke
. Par exemple, ce fragment de html:
<blockquote style="color: darkblue">
Du texte bleu avant un rond orange:
<svg width=10px height=10px>
<circle cx="5" cy="5" r="5" fill="orange"/>
</svg>
</blockquote>
Donne cela:
Du texte bleu avant un rond orange:
On peut varier, la couleur du texte et la couleur du rond indépendamment:
Du texte bleu avant un rond bleu:
Mais ce qu’on veut, c’est que le svg soit dessiné avec la couleur du texte. L’astuce pour consiste à utiliser le mot-clé currentcolor
:
<blockquote style="color:darkgreen">
Du texte bleu avant un rond de la même couleur :
<svg width=10px height=10px>
<circle cx="5" cy="5" r="5" fill="currentcolor" /> <!-- ici -->
</svg>
</blockquote>
Ça donne ça :
Du texte bleu avant un rond de la même couleur :
Tous les svg dans le même fichier
Si vos symboles se limitent à des petits ronds, félicitations, c’est fini ! Comme le svg des symboles est souvent nettement plus complexe et est composé d’un ou plusieurs path
avec leur syntaxe un poil absconse, on préfère éviter de les répéter dans le DOM à chaque utilisation.
svg use
à la rescousse
Le langage SVG permet de déclarer des symboles et de leur donner un identifiant:
<svg>
<symbol id="icon_name">
...
</symbol>
</svg>
On peut ensuite les utiliser avec l’élément use
:
<svg><use href="#icon_name"/></svg>
Tous les symboles svg peuvent être réunis dans un seul fichier. Ça donne ça, avec l’icône de mastodon, chargée depuis le fichier icons.svg:
<svg width=20px height=20px><use href="/img/icons.svg#fa-mastodon"/></svg>
Un éléphant ça trompe énormément.
Quelques détails techniques pour finir:
-
Dans le fichier svg, nous avons effectivement mis les icônes dans des éléments
<symbol>
, eux-mêmes réunis dans un élément<defs>
. Ces deux éléments n’ont pas d’incidence technique : on obtiendrait le même résultat avec desg
, mais comme dit la MDN: theypromote understandability of the SVG content and is beneficial to the overall accessibility of the document
. -
Note: le contenu du svg est shadowed dans le DOM de la page, ce qui signifie qu’il n’est pas accessible au JS ou au CSS. Autrement dit, vous ne pouvez pas appliquer un style CSS aux symboles. Cependant,
currentcolor
est bien pris en compte! Si on veut plus de liberté, il faut embarquer le svg dans le HTML. Là, vous pouvez faire tout le css que vous voudrez.
Comme je le disais au début, ce n’est pas une technique moderne ! C’est supporté par tous les navigateurs depuis une bonne dizaine d’années. Malheureusement, un bon paquet des collections d’icônes largement utilisées sont basées sur l’utilisation de polices de symboles. C’est d’ailleurs pour ça que FontAwesome s’appelle comme ça — mais ça ne nous empêche pas d’utiliser les glyphes de FontAwesome dans des svg.3
C’est tout pour cette fois-ci: la prochaine fois, on parlera de variables css et de design adaptatif sans media queries.
-
D’accord, il y a un poil de javascript, mais c’est pour débugguer le CSS. ↩︎
-
Et sémantique, mais c’est un peu pareil. ↩︎
-
FontAwesome “free” est distribué en CC BY SA 4.0. J’ai le vague sentiment que le gros du travail de FontAwesome en 2024 est de faire de l’outillage et de la gestion de paquets, pas de dessiner des icônes. Gardons ce débat pour un autre jour. ↩︎