Je suis surpris de voir que les unités relatives ne font pas encore consensus dans la communauté Web, notamment sur la typographie. Nicolas Hoizey avait fait une chouette conférence sur le sujet, que je vous invite à aller voir ou revoir : Un petit pas pour l’em
, un grand pas pour le Web.
Dans sa grande mansuétude, il tue également un vieux troll qui dit que la taille de fonte par défaut est toujours de 16px : People don’t change the default 16px font size in their browser. Je résume : c’est souvent le cas, mais pas toujours.
Un autre point quand vous hésitez à choisir une unité, la question à vous poser est : de quoi dépend réellement la valeur que je veux mettre, de quel contexte ? (gardez toujours cela à l’esprit)
Maintenant que c’est posé, avançons ! Suite à un échange sur Twitter hier après-midi, les notions de respect des préférences utilisateurs ne semblent toujours pas claires, tout comme le comportement des media-queries. Alors décortiquons le tout avec des exemples très simples.
Notes : si vous souhaitez tester les exemples que je vais donner, sous Firefox, il faut aller dans Options, Contenus, et là vous pourrez changer votre taille de fonte par défaut. Afin de simplifier les exemples, je les ferai avec une taille de fonte par défaut de 16px et 32px, j’ai choisi le double juste pour des raisons de simplicité d’explication. Je ne redonnerai pas tout le code à chaque fois, il y aura des pens pour cela.
Une taille de fonte par défaut en pixels
html { font-size: 10px; }
Pourquoi dit-on que c’est mal ? Voici la raison : que ma taille de texte par défaut soit de 16px, 32px ou n’importe quoi, l’utilisation des pixels fera que le site imposera ses valeurs au visiteur. Le texte que j’ai paramétré sera affiché en 16px dans tous les cas.
C’est quand même gênant si j’ai paramétré mon navigateur pour qu’il affiche le texte plus grand ou plus petit par défaut. Ne le faites pas pour la typo, à aucun endroit. Vraiment pas.
Voir l’exemple sur Codepen : une taille de fonte par défaut en pixels.
Une taille de fonte par défaut en unités relatives
Pour cet exemple, je n’ai pas utilisé de pixels, mais des unités relatives. Rappelons que les em
sont fonction de la taille de fonte de leur parent, et les rem
(root-em
) sont fonction de la taille de fonte de l’élément racine, soit html
.
Avec une taille de fonte par défaut à 16px, pas de souci, le texte est bien affiché en 16px et le titre h1
en 32px.
Si je mets ma taille de fonte par défaut à 32px dans mon navigateur, le texte sera donc bien affiché en 32px et le titre h1
en 64px. Là, les valeurs utilisées respectent les préférences de l’utilisateur.
Voir l’exemple sur Codepen : une taille de fonte en unité relative (em
).
Avec l’unité rem
, le résultat est exactement le même, les préférences utilisateur sont respectées. Voir une taille de fonte en unité relative (rem
).
Ok, en relatif, mais avec ou sans « reset » ?
Une pratique assez courante est d’utiliser ce genre de propriété sur l’élément html
:
html { font-size: 62.5%; }
À quoi cela sert ? C’est une simple astuce pour se simplifier le calcul (que moi-même j’utilise dans Röcssti). En partant de l’idée que la taille « standard » est de 16px, 62,5% de ces 16px donneront 10px à l’affichage.
Mais alors, on ne respecte plus les préférences utilisateur ???
Bien sûr que si, on les respecte. C’est pour cela que je mets « reset » entre guillemets. Comme c’est un chiffre rond, cela simplifie juste les calculs, surtout pour l’unité rem
. Avec ce « reset », 10px équivalent en permanence à 1rem. 1.4rem donne… un affichage de 14px, et ce où que l’on soit dans le document (sur le body
ou ailleurs).
Si vous n’êtes pas convaincu, testez une taille de fonte en em
sans « reset » ou une taille de fonte en rem
sans « reset ». Les préférences utilisateur sont respectées et le résultat est le même.
Bref, avec ou sans « reset » et en em
ou en rem
, le résultat est le même, seules quelques valeurs changent. C’est juste un peu de gymnastique intellectuelle, à votre convenance ! Si vous préférez que 1rem
soit équivalent à 10px pour vos calculs ou qu’il soit égal à « une fois la taille de fonte par défaut », c’est à votre convenance, je ne suis pas sectaire.
Le seul souci de ce « reset » est sous Internet Explorer (du 9 au 11). Une bête erreur d’arrondi peut fausser les valeurs affichées des fontes, cela se fixe ainsi :
html {
font-size: 62.5%;
font-size: calc(1em * 0.625); /* fix */
}
Bref, pas dramatique.
Pourquoi les gens n’aiment pas le « reset » ?
En fait, c’est souvent à cause d’un oubli : le « reset » est appliqué sur html
mais il n’y a pas de taille par défaut sur le body
. Du coup, le moindre oubli fait qu’on se retrouve avec une taille de fonte affichée à 10px, ce qui est rikiki et souvent très disgracieux au milieu d’un beau site.
Des em
ou des rem
?
Cela dépend de votre contexte. Même si je suis un très gros utilisateur des em
, je les utilise surtout parce que mon contexte s’y prête bien. Ajoutons à cela que les em
fonctionnent partout, même sur les vieux Internet Explorer !
Les em
nécessitent :
- soit un minimum de conventions posées,
- soit une certaine vision d’ensemble.
Et ce afin de pouvoir gérer l’héritage de la taille de fonte du parent.
Si vous avez une équipe éclatée sans aucune vision d’ensemble sur la CSS, avec des modules développés de manière complètement autarcique, les rem
seront sûrement plus faciles à gérer, vous n’aurez pas de souci d’héritage. Les rem
ont cependant une petite faiblesse, ils ne sont pas du tout supportés sur Internet Explorer 8 et inférieurs.
Sur des projets plus simples à cadrer ou avec des guidelines bien posées, les em
se gèrent sans trop de souci.
Après, on voit souvent cette notion d’héritage dans les em
comme quelque chose de compliqué, mais cela peut aussi être une force. Un module défini en em
, si l’on doit le réutiliser dans une zone différente où la taille de fonte sera plus grande, évoluera tout naturellement avec son contexte. Par exemple, un helper genre margin-top: 1em
s’adaptera où qu’il soit.
Croyez-moi sur parole, dans certains cas comme pour l’obtention et la conservation d’un rythme vertical, c’est très utile. Et dites vous que vos espacements s’adapteront en fonction des préférences utilisateur.
Mon guide de survie avec les em
Quand je commence une intégration, la première question que je pose est la taille du texte courant. Car quasiment tout va dépendre de cela.
Une fois que je la connais, j’applique cette valeur sur le body
(avec ou sans « reset » sur html
).
Ensuite, je calcule les tailles pour les Hx
et autres classes comme .big
, etc. (automatisé par un pré-processeur ou via le Röcssti-Builder).
Après, je crée le site dans les conditions « standards », et ô miracle, changer la taille de fonte par défaut ne cassera rien.
Contrairement à ce que beaucoup de gens croient, appliquer une classe qui modifie la taille à un élément dont la taille est également directement modifiée en em
ne pose pas de souci. Par exemple, un h1 class="h2"
sera bien à la taille de la classe .h2
(vu que c’est le parent qui sert de référence). Les soucis ne sont pas là !
Par contre, les em
sont compliqués quand on commence à imbriquer les classes modifiant les tailles, genre un span class="big"
dans un h2
.
En pratique, j’évite les imbrications hasardeuses, pas ou peu de souci d’héritage et tout se passe comme un charme.
Même mes collègues qui étaient – doux euphémisme – très réfractaires aux em
s’y sont plutôt bien habitués, donc c’est bien preuve que c’est possible. :)
Alors on doit jeter les pixels aux oubliettes ?
Du calme ! Et je n’ai pas dit ça ! :)
Oui, jetez-les pour la typo. Utilisez les em
, et si c’est compliqué, foncez sur les rem
. Mais quoi qu’on en dise, les pixels sont bien pratiques pour discuter avec un graphiste ou un client (qui n’a aucune notion des unités relatives). C’est une unité plutôt intuitive – quoique cela se discute dès qu’on commence à discuter écran à haute densité de pixels – et que tout le monde comprend. En gros, parler en pixels est une simplicité pour l’esprit.
L’autre cas problématique est lié aux arrondis, notamment sous Chrome/Webkit. Si vous avez un sprite avec diverses images et que vous dimensionnez en em
l’élément dans lequel l’image va s’afficher, des fois les arrondis sont foireux et même si la valeur est bien censée donner 15px, il peut y avoir des dépassements, catastrophique si les images dans le sprite sont serrées. Bref, dans ce cas, autant utiliser les pixels.
Idem pour les images. Ceci dit, si l’on garde la question du début « de quoi dépend réellement la valeur que je veux mettre, de quel contexte », pour une image, la réponse est tout simplement : d’elle-même. À méditer.
Et pour les media-queries ?
Je m’aperçois que ce billet est déjà bien long, je vous propose d’y revenir dans un prochain billet. N’hésitez pas à tester et à réagir.
Ajout : suite de ce billet dans Les media-queries et les préférences utilisateurs.
C'est le même principe qu'avec le SVG — le vectoriel en général — puisqu'on dessine des vecteurs (des trajectoires) qui sont positionnés les uns par rapport aux autres, indépendamment d'un contexte strict. C'est ce qui fait que peu importe la dimension d'affichage, le tracé vectoriel sera toujours bien proportionné et de bonne qualité.
Les em c'est pareil. Et c'est chouette.
Et oui je sais je fais des raccourcis, mais conceptuellement c'est pas loin :p