Personnaliser les select

Voir la vidéo

C'est officiel, on peut enfin personnaliser les éléments <select> en CSS ! Plus besoin d'utiliser des librairies JavaScript pour avoir un menu déroulant qui colle à notre design. Ce n'est pour le moment disponible que pour les navigateurs basés sur Chromium (à partir de la 135) mais on espère que les autres navigateurs vont suivre.

Dans cet article je vous propose d'explorer le fonctionnement de cette nouveauté.

Sources

Fonctionnement

Réinitialiser le style

La première étape est de demander au navigateur de changer le style du select pour ne plus utiliser le select de base mais le select implémenté par le navigateur.

select,
select::picker(select) {
  appearance: base-select;
}

Avec ce style, le select change d'apparence. Il passe d'un look "système" à un look "navigateur" minimaliste, prêt à être stylisé.

Styliser le Bouton Select

Pour le style voici les éléments clefs qu'il est possible de sélectionner.

select {
  /* Style du bouton select */
}
select::picker-icon {
  /* Pseudo élément représentant la flêche */
}
select::picker(select) {
  /* Menu déroulant */
}
option::checkmark {
  /* Coche à gauche des options */
}

De l'HTML dans les options !

On peut maintenant mettre du HTML directement dans nos balises <option> !

Imaginons qu'on veuille afficher un avatar à côté du nom dans notre sélecteur d'utilisateurs :

<select>
  <option value="1">
    <img src="/avatar-bastien.jpg" alt="" width="20" height="20" />
    Bastien
  </option>
  <option value="2">
    <img src="/avatar-alice.jpg" alt="" width="20" height="20" />
    Alice
  </option>
</select>

Bouton personnalisé

Si vous sélectionnez une option avec du HTML (comme notre avatar), le bouton select n'affichera que le contenu textuel par défaut. Pour améliorer cela il est possible de mettre un <button> comme premier enfant du <select> et on peut utiliser une balise spéciale <selectedcontent> qui reprendra automatiquement le contenu de l'option sélectionnée.

<select>
  <!-- Ce bouton sera affiché à la place du contenu par défaut du select -->
  <button>
    <!-- Prendra le contenu HTML de l'option choisie -->
    <selectedcontent></selectedcontent>
    <svg><!-- ... icône flèche ... --></svg>
  </button>

  <!-- Ensuite nos options -->
  <option value="1">
    <img src="/avatar-bastien.jpg" alt="" width="20" height="20" />
    Bastien
  </option>
  <option value="2">
    <img src="/avatar-alice.jpg" alt="" width="20" height="20" />
    Alice
  </option>
</select>

Positionnement

Le menu déroulant se positionne automatiquement mais il est possible de choisir son emplacement à l'aide du système d'(ancrage CSS)[https://developer.mozilla.org/en-US/docs/Web/CSS/anchor].

select::picker(select) {
  /* On positionne le menu sur la droite de notre select */
  top: anchor(top);
  left: anchor(right);
}

Animations

On peut aussi ajouter des animations pour le déploiement du menu déroulant.

select::picker(select) {
  opacity: 0;
  transform: translateY(-10px);
  transition: all 0.4s allow-discrete;
}

select::picker(select):popover-open {
  transform: translateY(0px);
  opacity: 1;

  @starting-style {
    opacity: 0;
    transform: translateY(-10px);
  }
}

Et les autres navigateurs ?

Cette nouveauté est une amélioration progressive. Les navigateurs qui ne comprennent pas appearance: base-select, ::picker(select), ou le HTML dans les options vont simplement ignorer tout ça et afficher le bon vieux select natif standard. Le contenu HTML dans les <option> sera ignoré, seul le texte sera pris en compte.

Limitations

Cette nouvelle option de style permettra de se passer de librairies JavaScript pour de nombreux cas mais attention à quelques points :

  • Il n'est pas possible de mettre un champ dans le select (bloquant pour créer un autocomplete par exemple).
  • Sur mobile, l'apparence base-select désactive le sélecteur natif pour notre menu déroulant, donc à voir ce que ça donne niveau accessibilité.

Conclusion

Pouvoir styliser les selects nativement, c'est quelque chose qu'on attendait depuis des années et ce changement va enfin permettre de créer des interfaces plus cohérentes et esthétiques sans alourdir nos pages avec du JavaScript surtout que c'est le navigateur qui va gérer toute la partie accessibilité (navigation clavier, etc.), ce qui est un énorme avantage.

En revanche, je trouve l'approche un peu exotique (le <button> + <selectedcontent>, les pseudo-éléments ::picker(select), ::picker-icon, ::checkmark) au premier abord. Il y a une certaine logique derrière mais ça demande un petit temps d'adaptation.

Publié
Technologies utilisées
Auteur :
Grafikart
Partager