FBI (Fausse Bonne Intégration) : ces astuces et bonnes pratiques qui sabotent vos sites et apps web

Publié le 07/07/26par Amy Ndiaye

Niveau : découverte

Rien de tel qu’une bonne astuce pour faciliter le quotidien (parfois douloureux) des équipes front-end.

Fermez les yeux et imaginez vous au bureau. Il vous reste 10 minutes avant le daily. Vous êtes confortablement assis·e sur votre chaise. Muni·e de votre souris, vous parcourez vos notifications Slack ou Teams (quand ça fonctionne). Dans le canal « Veille Front », vous découvrez l’article partagé par un membre de votre équipe : « 10 astuces et bonnes pratiques pour intégrer au pixel près ».

Clic, vous êtes rédirigé·e vers une page bien écrite, soignée et en thème sombre. Vos yeux brillent ! Devant vous, un condensé de bonnes pratiques et astuces illustrées, expliquées et justifiées. Ni une ni deux, vous les adoptez dans votre codebase. Vous répandez la bonne parole à vos collègues, à vos ami·e·s dev et/ou à travers un poste sur votre réseau social de prédilection.

Puis 3 jours, 3 mois ou 3 ans plus tard, vous découvrez avec stupeur les effets de bords de ces « astuces » ! Le mal est déjà fait. Vous y avez cru, vos collègues y ont cru, le monde y a cru et vos utilisateurs en ont pâti.

Mais de quelles astuces s’agit-il ? Est-ce que je les utilise ? Si oui, comment réparer le mal fait ? Sont-elles si problématiques que ça ? Ai-je une bombe à retardement dans mon code ?

La réponse à ces questions se trouve dans ce talk…

Transcript

Introduction

Moi c’est Amy, j’ai vingt minutes pour vous parler de ça, donc vous ne saurez pas plus que mon prénom : « Fausse Bonne Intégration », ces astuces et bonnes pratiques qui sabotent vos sites et applications web.

Petit disclaimer avant de commencer : si jamais vous reconnaissez des astuces que vous avez utilisées par le passé, ou que vous utilisez encore, ce n’est pas grave, ce n’est pas pour vous blâmer. De temps en temps, je vous demanderai de lever la main si vous avez déjà vu passer ce genre de code — je n’ai pas de projectile, donc c’est bon. Et puis moi-même j’ai fait certains des trucs dont je vais vous parler, donc pas de panique, on est en toute décontraction, je tremble un peu mais ça va.

J’ai créé un site fictif de stickers qui s’appelle Stickit — vous voyez le jeu de mots, hilarant, let’s go. Donc voilà notre fameux site fictif, notre site de stickers Stickit. C’est ce site qui va nous servir d’exemple, parce que je ne voulais pas prendre un vrai site au risque de froisser des gens dans la salle.

Ça, c’est notre magnifique victime — le mobile, on s’en fout, on verra ça plus tard. On a un petit bord en liège avec des post-it, et cetera : ça existait vraiment chez moi, ça m’aide à visualiser. On va voir différentes catégories : les erreurs en termes de texte, de layout, de ce qu’on veut cacher, de ce qu’on veut reset, et cetera.

Texte : la fausse bonne idée des 62,5 %

On va d’abord commencer par tout ce qui est texte. Petite question : est-ce que « 62,5 % » dit quelque chose à quelqu’un dans la salle ? Une personne, c’est déjà bien.

Pour gérer les tailles de police, on conseille d’utiliser les rem, sauf que nos maquettes sont souvent en pixels, et du coup c’est pénible de faire la conversion. Il y a plusieurs manières de faire : on peut passer par de petits utilitaires en ligne, ou faire les calculs nous-mêmes parce qu’on est super intelligents. Mais moi je suis une flemmarde, et un jour je suis tombée sur cette super astuce qui consiste à cibler le html et à mettre font-size: 62,5%. Ce que ça fait, c’est qu’un rem devient égal à 10 pixels, et du coup la conversion se fait super facilement : par exemple, mon titre est en 48 pixels, ça fait 4,8 rem. C’est simple, on aime.

Sauf que — pardon, sauf que — ça s’appuie sur le fait que les navigateurs ont une taille de police par défaut de 16 pixels. Mais peut-être que vous avez des collègues qui n’ont pas une super bonne vue, ou des grands-parents, ou des parents qui ont leur navigateur super zoomé avec la police à 24. Du coup, cette astuce-là ne fonctionne plus, parce que votre conversion ne sera plus « un rem égale 10 pixels », ce sera totalement autre chose, et vous n’aurez plus la maîtrise. Et vu qu’on ne maîtrise pas très bien le responsive dans ce cas-là, il y a de grandes chances que votre bouton, avec un texte normalement à 16 pixels, se retrouve à 64, et que tout soit explosé sur votre site — et que vous ayez un charmant ticket de bug que vous n’arrivez pas à reproduire, parce que vous avez, vous, une vision standard.

Il y a des solutions. La première, la classique, c’est d’utiliser calc() en CSS. Après, calc est une fonction, il y a peut-être des soucis de perf potentiels, mais en tout cas ça existe : il suffit d’écrire une formule du type calc(48 / 16 * 1rem), et ça convertit automatiquement, vous ne vous prenez pas la tête.

Autre solution, si vous utilisez un préprocesseur : vous pouvez écrire une fonction ou un mixin qui prend en paramètre une valeur en pixels et qui retourne une valeur en rem, et là non plus vous ne faites pas de maths.

Dernière solution, ma préférée, qui utilise des nouveautés pas si nouvelles que ça de CSS : les variables. J’ai mis un exemple un peu bateau, mais si par exemple vous avez un design system, vous pouvez reprendre les termes utilisés par votre designer et nommer vos variables comme ça. Moi j’ai mis, par exemple, 48 pixels qui font 3 rem, et du coup j’ai juste à utiliser var() avec le nom de ma variable pour mettre la bonne taille.

Voilà pour cette première astuce, que j’ai mise en prod — et malheureusement je ne suis plus dans la boîte qui l’utilise, donc je vais leur envoyer un message pour leur dire : enlevez ça, vite, vite.

text-wrap: balance

Deuxième astuce : text-wrap. Celle-là, vous l’avez peut-être vue passer, parce qu’elle a fait le tour sur Twitter, elle a été beaucoup relayée.

En gros, c’est pour « balancer » votre texte — enfin, ce n’est pas français, pour l’équilibrer, éviter d’avoir un mot qui se balade tout seul, et avoir un titre ou des paragraphes harmonieux. Il y a une propriété qui s’appelle text-wrap, qui peut prendre comme valeur balance ou pretty. Et c’est cool, parce que ça équilibre le texte automatiquement.

C’est cool, mais comment ça marche sous le capot ? Ça boucle sur chaque caractère de l’élément ciblé, donc potentiellement, sur une page qui a beaucoup de texte, ce n’est pas super conseillé. En plus, ça ne s’applique qu’à la dernière ligne, donc ça va aller chercher tous vos titres par exemple. Dans mon exemple, j’avais mis une petite étoile à côté de text-wrap : l’idée, c’est que si vous voulez l’utiliser parce que vous avez un designer qui veut absolument qu’il n’y ait pas de veuve ni d’orpheline, vous pouvez, mais uniquement sur les titres — donc h1 à h6, les citations. Pour les paragraphes, je vous propose plutôt de faire une classe utilitaire et de l’utiliser avec parcimonie, là où vous en avez vraiment besoin, pour éviter des soucis de perf liés au CSS. Ce serait dommage — on a déjà JS pour ça, on ne va pas le concurrencer.

Reset : list-style

Ensuite, tout ce qui est reset : l’idée d’enlever le style par défaut appliqué par notre navigateur. Par exemple les listes à puces : par défaut, un ul (unordered list) a des puces, c’est moche, et ce n’est pas ce qu’on veut, parce qu’on veut faire une belle navigation où tous les éléments sont les uns à côté des autres.

Donc souvent, on met un list-style: none. Est-ce qu’il y a des gens qui ont déjà fait ça ? Je vous rassure, moi aussi. Et la suite va vous surprendre : le souci, c’est Safari. Si vous avez déjà entendu la phrase « Safari, the new IE », voilà, parce que je vais vous donner un exemple. En gros, si vous ciblez le ul et que vous mettez list-style: none, ça ne marchera pas sur Safari : votre liste perd son rôle « liste », donc elle n’est plus sémantiquement correcte. Par contre, si vous mettez votre ul dans une balise nav et que vous ciblez avec ce sélecteur-là, ça marche sur Safari. Par contre, si vous utilisez les sélecteurs plus récents avec :where(), en spécifiant bien que ce sont les ul qui ont le rôle « liste », et que vous mettez list-style: none, la liste ne sera toujours pas reconnue comme une liste. Et si vous ciblez juste le ul en mettant list-style — pas à « none » cette fois-ci, mais vide — ça sera reconnu comme une liste. Bref, Safari n’est pas très stable là-dessus.

Je vous propose tout simplement — malheureusement je n’ai pas de solution miracle — d’aller remettre le rôle « liste » sur vos éléments. Après, parfois la question, c’est : est-ce que vous avez vraiment besoin d’une liste ? Une liste, on peut l’utiliser dans une navigation pour faire une liste de liens, mais on peut faire aussi une liste de produits, et dans ce cas-là vous pouvez par exemple utiliser une balise article, et là vous n’avez pas besoin de surcharger le style. J’ai dit article, pas div, parce que je mène le combat anti-div : pas de soupe de div, évitez les div, il y a des balises sémantiques, utilisez-les, s’il vous plaît, merci — ceux qui étaient là l’année dernière connaissent déjà mon combat.

Reset : outline

Même délire pour supprimer le style des bordures ou des boutons : il y a déjà des gens qui ont fait border: none — c’est normal, par pitié, résistez, vos designers sont fous — mais surtout, l’outline, ça a une utilité : quand vous naviguez au clavier, ça permet de voir quel élément a le focus. Si vous supprimez l’outline, on ne voit plus sur quoi on est.

Deuxième chose : si votre utilisateur utilise le mode fort contraste, ça va changer les bordures et les contours, et si vous les avez supprimés, ça ne marchera tout simplement plus. Donc si vraiment vous devez les enlever visuellement, mettez-les en transparent plutôt qu’en none : vous les rendez invisibles, mais ça ne casse pas le mode fort contraste. Dans le futur, vous pourrez utiliser une media query spécifique pour détecter ce mode et appliquer un style en conséquence. Mais de manière générale, laissez les outline tranquilles — vous pouvez plutôt les personnaliser avec la charte graphique de votre entreprise pour faire quelque chose d’un peu plus joli, mais laissez-les, s’il vous plaît, merci, c’est tout pour moi.

Cacher un élément : visually-hidden et sr-only

Ensuite, « caché » — normalement ça devait être écrit « cache-cache », mais j’ai oublié de le corriger, je trouvais ça plus drôle comme ça.

L’idée, c’est visually-hidden, ou sr-only : est-ce que ce sont des noms qui vous disent quelque chose ? Je vais expliquer vite fait. En gros, quand vous avez un élément que vous voulez rendre accessible aux lecteurs d’écran, mais pas aux personnes qui voient votre site, vous utilisez une classe utilitaire qui s’appelle souvent visually-hidden, ou sr-only si vous utilisez Tailwind.

Qu’est-ce que ça fait ? Première ligne, position: absolute : ça sort l’élément du flux de la page. Ensuite, width: 1px : l’élément ne fait plus qu’un pixel carré, et l’overflow coupe tout ce qui dépasse. Ensuite, clip-path permet de supprimer l’affichage — par exemple, si votre élément avait du rouge en fond, on le verrait sinon. Et enfin, white-space: nowrap évite que le texte passe à la ligne. Concrètement, sur le site vous ne voyez pas l’élément, alors qu’il est bien présent dans le code.

C’est un truc que j’ai découvert récemment, parce que je l’utilisais beaucoup en accessibilité, notamment pour ce qu’on appelle les skip links. Ce sont des petits liens : si vous naviguez au clavier sur un site et que vous appuyez sur Tab, un lien apparaît qui vous permet de sauter directement au contenu principal, sans avoir à vous taper tous les liens inutiles. Ikea a ça, et c’est bien implémenté, donc bravo à eux. Il y a un exemple du type « Aller au contenu principal ».

L’idée, c’est vraiment d’ajouter un sélecteur du type .skip-link:not(:focus):not(:active), ce qui veut dire : cacher l’élément lorsqu’il n’a pas le focus et qu’il n’est pas actif. Pourquoi ? Parce que si vous voulez que votre utilisateur puisse interagir avec l’élément et que vous mettez juste visually-hidden en dur, ça peut poser des problèmes d’interaction. L’idée, c’est vraiment de dire : si tu es actif, ce code ne s’applique pas. C’est le cas par exemple pour ce bouton : dès que je fais Tab, le focus passe dessus, et je peux quand même interagir, appuyer sur Entrée, et ça me redirige vers la bonne section. Si vous utilisez Tailwind, ça donnerait quelque chose comme .sr-only:focus, .sr-only:active — bon, il fallait peut-être pas prendre Tailwind comme exemple pour cette partie-là.

Bouton icône

Ensuite, bouton icône : ça, c’est peut-être un truc que vous avez fait — votre designer vous a demandé une super navbar, et il y a un bouton qui n’a pas de libellé. Je ne conseille pas. On se dit que tout le monde comprend le cœur, sauf que, patatras, un jour votre CSS, pour X ou Y raison, ne charge pas — ça arrive plus qu’on ne le pense. Du coup, ou même si votre SVG ne charge pas, votre utilisateur ne voit rien : il ne sait pas qu’il y a un lien, il ne peut pas cliquer.

Qu’est-ce qu’il faut faire ? L’idée la plus simple, c’est d’ajouter un span dans le bouton, de lui mettre la classe visually-hidden qu’on a vue avant — le span n’est pas focusable, c’est le bouton qui l’est, donc pas besoin de se prendre la tête là-dessus — et de mettre votre libellé entre les balises du span. Du coup, si le CSS ou le SVG ne charge pas, votre bouton reste toujours interactif. Il y a une autre solution, un peu plus compliquée, avec aria-label ou aria-labelledby, mais la règle des ARIA, c’est d’éviter d’en utiliser si on peut, parce que c’est compliqué. Toujours préférer une solution HTML pure.

Layout : Flexbox et Grid

Et là vous voyez « Flexbox », vous vous dites : mais qu’est-ce qu’elle raconte, Flexbox c’est la vie, elle est folle. Oui, mais ça, c’est un truc que j’ai codé il y a quatre ou cinq ans : on m’a demandé de faire une grille de produits, donc j’ai fait du display: flex, justify-content: space-between — il n’y avait pas encore de gap à l’époque, donc je gérais mes marges un peu bizarrement.

Ce qui s’est passé, c’est que quand mes pages avaient le bon nombre de produits, tout était aligné parfaitement. Mais dès qu’on arrivait sur la dernière page, on se retrouvait avec deux cartes espacées comme si elles avaient divorcé. Et là, tu es en mode « qu’est-ce que je vais faire ». Donc tu vas sur Stack Overflow, à l’époque, parce qu’il n’y avait pas encore ChatGPT, et on te propose de mettre des pseudo-éléments, de calculer en JS pour placer la carte. Non, non, non : il y a Grid. En fait, Grid, c’est deux lignes (le gap, je ne le compte pas), et voilà, c’est carré, peu importe le nombre de cartes, ce sera toujours aligné et beau. Et je sais, Grid ça fait peur, moi-même je trouve ça un peu pénible, mais du coup j’ai appris deux choses avec : faire une grille basique, et centrer un élément. Je vous le conseille : si vous voulez commencer avec Grid, faites déjà ça, et vous pourrez faire beaucoup de choses.

display: contents

Dernière chose : display: contents. Dans de rares cas — vous savez, Flexbox, c’est une histoire de flex item et de flex parent — imaginez une nav qui est en flex : elle est le parent, et ses enfants directs, ses flex items, seraient techniquement un ul et une div. Ça veut dire que si je fais un justify-content: space-between, ce serait mon ul et ma div qui se retrouveraient côte à côte. Sauf que moi, je préférais aligner les éléments enfants de ces deux éléments-là, donc mes li et mes a. Ce que je peux faire, c’est utiliser display: contents sur le ul et sur la div. Si je fais ça, c’est comme si les boîtes n’existaient plus, et les enfants directs de ma nav deviennent mes li et mes a. C’est plus facile ensuite de gérer les gap, et ça peut être pas mal si vous avez une nav avec une barre de recherche, des éléments de navigation, des boutons — parce que les alignements verticaux et horizontaux, parfois, c’est pénible. Voilà, c’est cool.

Non ? Pourquoi ? Parce qu’il y a des devs qui militent pour qu’on arrête d’utiliser display: contents : ce n’est pas stable sur Safari, mais pas seulement. Ce que ça fait, en fait, c’est que ça supprime votre boîte, elle n’est pas rendue. Et si votre boîte avait une valeur sémantique — par exemple un ul, qui a le rôle « liste » — normalement le li est enfant du ul, mais là ce n’est plus le cas : vous vous retrouvez avec des éléments qui ont le rôle « item de liste » sans parent portant le rôle correspondant. Ça peut poser des problèmes d’accessibilité, et si vous travaillez pour une grosse boîte ou un service public, il faut vraiment faire attention à ce genre de choses.

Donc on aimerait bien pouvoir utiliser display: contents, mais ce n’est pas encore vraiment possible. En attendant, je vous en parle quand même, parce que le jour où ça marchera vraiment, ça va sauver des vies — mais ce n’est pas le cas aujourd’hui, donc ne l’utilisez pas. Ça aussi, je l’ai vu tourner sur Twitter, et les gens étaient en mode « oui, oui, on va l’utiliser ». Non, s’il vous plaît, ne l’utilisez pas. Si vous voulez quand même l’utiliser, faites-le sur des éléments non sémantiques, par exemple une div, ce sera ok. Et sinon, débrouillez-vous pour aligner vos éléments sans display: contents, à la bonne franquette, comme on faisait avant.

Conclusion

Pour conclure : d’où vient le souci, d’où viennent toutes ces « bonnes pratiques » — utiliser visually-hidden, les 62,5 %, et cetera ? Ce sont des choses qui sont là depuis des années : le truc des 62,5 % émerge en 2004, a été popularisé en 2016, et est revenu en 2020. Il y a des astuces qui sont là depuis longtemps, mais c’est simplement parce qu’on essaie de se faciliter la vie, de se donner de bons conseils, de partager. Il y a aussi des influenceurs tech qui partagent des astuces sans vraiment creuser, ou sans donner toute la vérité. Donc si vous voyez une astuce et que vous avez un doute, testez-la, et si vous avez encore des doutes, vous pouvez venir sur le site de cascade.fr : il y a un Discord de passionné·e·s d’intégration, ça touche au CSS, au HTML, et cetera, avec un canal d’aide. Dernièrement, on y a parlé de la meilleure façon d’intégrer des SVG dans un site — sprites ou icon fonts pour les icônes — c’était passionnant.

Donc si vous aimez le CSS, le HTML, si vous avez des questions, n’hésitez pas à venir. Vous pouvez me suivre sur LinkedIn et me laisser un retour. Et là, on ne le voit pas, mais il y a une photo de mon chat, qui aimait beaucoup s’asseoir devant mon ordinateur pendant que je préparais cette conférence — et effacer des choses aussi. Et ça, c’est moi quand j’ai fait cette conférence.

Voilà, merci.