/ Articles
La malédiction des select enfin levée ? 👨🎨
That old pal
Tout développeur front connaît comme sa poche le <select> pour créer un menu déroulant 👇
Au grand dam des développeurs, ce <select> était pourtant très peu personnalisable.
Impossible, par exemple, de changer directement la flèche à droite du sélecteur ou l'apparence du menu déroulant sans des stratégies de contournement qui donnaient toujours l'impression de travailler contre la plateforme web (et ses archaïsmes) plutôt qu'avec.
De guerre lasse, on se retrouve généralement coincé avec un rendu visuel dicté par le navigateur et le système d'exploitation de l'utilisateur qui va donner à notre <select> une apparence variable d'un client à un autre. Vraiment pas l'idéal pour un site qui cherche à maintenir une cohérence visuelle et offrir la même expérience à tous ses visiteurs...
La tentation est alors forte de recréer soi-même un <select> à l'aide de quelques <div> ou <button> saupoudrées de JavaScript ou de se tourner directement vers des librairies de composants empruntant déjà cette voie pour nous donner la main complète sur son apparence.
Jetons un œil par exemple au select de la librairie Shadcn UI, l'une des bibliothèques de composants les plus populaires 👇
Même fonctionnement, même apparence. On croirait un vrai ! 🪞✨
À la lecture du code source, on réalise toutefois qu'il n'y a aucun <select> en vue mais seulement un <button> bardé d'attributs et qui requiert d'importer une librairie JavaScript (ici @radix-ui/react-select) pour pouvoir fonctionner comme un <select> natif...
En quoi est-ce problématique ? D'abord parce qu'en s'en remettant à l'API d'un composant externe, on perd le bénéfice d'une implémentation native et performante du composant <select> optimisée pour le navigateur. Ces implémentations alternatives requièrent toute une série d'attributs pour satisfaire les standards d'accessibilité. Ensuite parce que cela nous contraint à ajouter une dépendance à notre projet pour émuler un comportement déjà existant à la seule fin de contourner des limitations stylistiques...
Quitte à devoir utiliser des <button> et des <div> pour contrefaire notre <select>, pourquoi ne pas tenter une implémentation personnelle afin de ne pas se reposer sur une librairie externe pour un composant aussi essentiel ?
Parce que rien n'est moins simple ! Bien des difficultés vous attendent en raison des nombreux aspects fonctionnels que doit émuler un menu déroulant digne de ce nom :
- Navigation au clavier et gestion du focus, notamment pour l'accessibilité ;
- Adaptation mobile ;
- Détection du clic à l'extérieur pour la fermeture ;
- Repositionnement automatique selon la bordure de fenêtre la plus proche ;
- Chevauchement possible avec d'autres éléments notamment lors du scroll.
😮💨
Chrome notre sauveur (again)
Mais voilà que depuis peu, avec Chrome et les navigateurs basés sur Chromium comme Edge, on peut enfin styliser un <select> jusque dans ses moindres détails tout en profitant de ses fonctionnalités natives !
Dans le cas où vous utiliseriez une version d'un navigateur qui ne supporte pas encore appearance: base-select, celui-ci ignore simplement cette propriété et affiche le <select> avec son style par défaut. Vous ne prenez donc pas trop de risque à le mettre en place comme une amélioration progressive (même si quelques différences subtiles peuvent apparaître qui sont détaillées plus bas).
La première étape consiste à désactiver le style par défaut du <select> choisi par votre navigateur (ombre, bordures, espacements, etc.) en optant pour la nouvelle propriété appearance: base-select.
On obtient alors un <select> complètement nu et totalement personnalisable !
Votre navigateur ne supporte pas actuellement cette fonctionnalité 🥲 Je vous conseille de basculer sur Chrome ou Edge en version desktop pour profiter de sa version interactive !
Certes rien de renversant à première vue... Celui-ci paraît même moins esthétique ainsi dépouillé de ses plus beaux atours. Mais croyez-moi, ce <select> offre des possibilités insoupçonnées.
Explorons-en quelques-unes ! 🎒
Insérer des images ou des SVG
En utilisant donc cette nouvelle propriété appearance: base-select, il est désormais possible d'insérer dans nos <option> des éléments visuels (images, SVG, etc.) qui étaient jusqu'à présent ignorés par le parser du navigateur. Exemple avec ce sélecteur de frameworks JavaScript 👇
Votre navigateur ne supporte pas actuellement cette fonctionnalité 🥲 Je vous conseille de basculer sur Chrome ou Edge en version desktop pour profiter de sa version interactive !
Le <select> customisable accepte de rendre n'importe quel bout de HTML dans ses <option> quand le <select> classique récupérait uniquement le premier nœud de texte qu'il trouvait, faisant fi du reste.
Customiser l'élément sélectionné
Bien souvent, la valeur d'un <select> change d'apparence une fois sélectionnée. La nouvelle balise <selectedcontent> permet de cibler l'élément lorsqu'il est sélectionné et de lui appliquer un style spécifique.
Le <selectedcontent> agit comme un emplacement libre à l'intérieur duquel se téléporte l'<option> sélectionnée.
Pour l'exemple, on peut reproduire le bouton GitHub de merge où l'option sélectionnée sur fond vert doit présenter un aspect différent de sa version plus détaillée affichée dans la liste déroulante 👇
Votre navigateur ne supporte pas actuellement cette fonctionnalité 🥲 Je vous conseille de basculer sur Chrome ou Edge en version desktop pour profiter de sa version interactive !
Il est également possible de glisser entre nos <option> du code additionel comme ici avec des balises <hr/> intermédiaires entre les options pour plus de lisibilité.
S'affranchir du menu déroulant
Cette flexibilité accrue dans la customisation des selects permet de plus des compositions plus originales qui sortent du seul menu déroulant ! On peut par exemple envisager de créer un sélecteur de réactions semblable à celui de Facebook en pur HTML et CSS 👇
Votre navigateur ne supporte pas actuellement cette fonctionnalité 🥲 Je vous conseille de basculer sur Chrome ou Edge en version desktop pour profiter de sa version interactive !
Certes, pour parvenir à un tel résultat il faut cibler des sélecteurs aux noms encore exotiques et jouer avec un panel de propriétés CSS plus important — notamment pour le positionnement des éléments qui passe par les propriétés anchor et les animations d'entrée et de sortie. En voici un petit aperçu pour ceux avec l'estomac bien accroché :
Beaucoup de magie noire par rapport à du CSS classique... Mais réjouissons-nous mes frères ! Car c'est une nouvelle barrière qui vient de tomber entre le rendu du navigateur natif et le pouvoir d'expression du CSS qui croît à grande vitesse depuis quelques années. Le plus tôt nous nous familiarisons avec ces syntaxes, plus rapidement nous évoluerons avec facilité dans le web du futur (si l'IA ne nous met pas au chômage avant...).
Quelques différences notables...
Lorsque vous passez en appearance: base-select; même à titre d'amélioration progressive, quelques différences subtiles sont à prendre en compte sans quoi vous risquez des surprises voire des régressions inattendues sur vos anciens <select>:
- Le
<select>customisable ne prend plus automatiquement la largeur de l'<option>la plus longue ; - Le
<select>customisable ne déclenche plus automatiquement les composants mobiles spécifiques — ce qui est cohérent avec l'objectif de garantir une expérience utilisateur unifiée entre toutes les plateformes pour lequel ce type de<select>a été mis en place.
À quand une compatibilité universelle ?
Comme souvent, Chrome passe en éclaireur pour pousser l'agenda des spécifications CSS à implémenter. Au moment de la parution de cet article, aucune date n'est encore annoncée pour les autres navigateurs du marché ou leurs versions mobiles.
Fait intéressant, sur leur blog Chrome for Developers il est précisé que d'autres éléments HTML bénéficieront bientôt de cette propriété appearance: base-*;. Il y a fort à parier que celle-ci devienne la propriété CSS standard pour désactiver complètement la feuille de style des navigateurs et offrir un contrôle plus fin sur des éléments historiquement assez verrouillés comme les checkboxes ou les boutons radio.