Back

Styliser les éléments Select avec CSS moderne

Styliser les éléments Select avec CSS moderne

L’élément <select> a toujours été l’un des contrôles de formulaire les plus récalcitrants à styliser. Contrairement aux inputs ou aux boutons, il s’affichait historiquement en utilisant des composants d’interface au niveau du système d’exploitation, ce qui signifie que CSS ne pouvait qu’effleurer la surface. Cette limitation a poussé les développeurs vers des solutions de contournement qui restent courantes dans le code de production aujourd’hui.

Cet article couvre les deux approches : la technique héritée largement supportée utilisant appearance: none, et le modèle plus récent appearance: base-select actuellement en émergence dans les navigateurs Chromium modernes.

Points clés à retenir

  • Les éléments natifs <select> résistent au stylage car les navigateurs ont historiquement délégué leur rendu au système d’exploitation, produisant des résultats incohérents d’une plateforme à l’autre.
  • La technique appearance: none, combinée à un élément conteneur et une flèche personnalisée via clip-path, est la méthode cross-browser la plus fiable pour styliser l’état fermé d’un select.
  • appearance: base-select (Chrome/Edge 135+) déverrouille des points d’accroche pour styliser le panneau déroulant, l’icône de flèche, les coches et le contenu sélectionné — mais uniquement dans les navigateurs basés sur Chromium actuellement.
  • Utilisez @supports (appearance: base-select) pour superposer l’approche moderne comme amélioration progressive au-dessus de la base héritée.

Pourquoi les éléments natifs <select> résistent au stylage CSS

Les navigateurs confiaient traditionnellement le rendu des <select> au système d’exploitation. Le résultat était un dimensionnement de boîte, un rendu de police et des styles de flèche déroulante incohérents entre Chrome, Firefox, Safari et Edge, sans moyen fiable de les unifier uniquement avec CSS.

La liste déroulante ouverte (le panneau d’options) reste largement non stylisable dans la plupart des navigateurs encore aujourd’hui. C’est une contrainte forte à garder à l’esprit avant de choisir votre approche.

L’approche héritée : appearance: none avec un élément conteneur

La technique de stylage CSS la plus largement supportée pour les éléments select implique trois étapes :

  1. Supprimer l’apparence native avec appearance: none.
  2. Envelopper le <select> dans un élément conteneur que vous pouvez styliser librement.
  3. Ajouter une flèche déroulante personnalisée en utilisant clip-path ou un SVG en arrière-plan.
:root {
  --select-border: #777;
  --select-arrow: var(--select-border);
}

select {
  appearance: none;
  background-color: transparent;
  border: none;
  padding: 0 1em 0 0;
  width: 100%;
  font-family: inherit;
  font-size: inherit;
  cursor: inherit;
  line-height: inherit;
  outline: none;
}

.select {
  display: grid;
  grid-template-areas: "select";
  align-items: center;
  position: relative;
  border: 1px solid var(--select-border);
  border-radius: 0.25em;
  padding: 0.25em 0.5em;
  background-color: #fff;
}

select,
.select::after {
  grid-area: select;
}

.select::after {
  content: "";
  width: 0.8em;
  height: 0.5em;
  background-color: var(--select-arrow);
  clip-path: polygon(100% 0%, 0 0%, 50% 100%);
  justify-self: end;
  pointer-events: none;
}

L’astuce de superposition CSS grid ici mérite d’être comprise : en assignant à la fois le <select> et le pseudo-élément ::after à la même zone de grille nommée, on les empile, permettant à la flèche personnalisée de se positionner visuellement au-dessus sans casser le comportement de clic du contrôle natif.

Pour les états de focus, puisque outline sur le select natif ne se comporte pas de manière fiable d’un navigateur à l’autre, une solution courante consiste à ajouter un élément frère <span class="focus"> et à le cibler avec select:focus + .focus en utilisant position: absolute pour dessiner un anneau de focus visible.

Cette approche fonctionne sur tous les navigateurs modernes et préserve l’accessibilité native — la navigation au clavier, les annonces de lecteur d’écran et la soumission de formulaire se comportent tous comme prévu.

L’approche moderne : appearance: base-select

Chrome 135 et Edge 135 ont introduit un nouveau modèle opt-in qui expose les parties internes du <select> pour un stylage CSS direct. Vous l’activez comme ceci :

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

Cela déverrouille plusieurs nouvelles cibles de stylage :

  • ::picker(select) — le panneau déroulant contenant les options
  • ::picker-icon — l’indicateur de flèche déroulante
  • option::checkmark — la coche affichée à côté de l’option sélectionnée
  • :open — une pseudo-classe active pendant que le picker est ouvert
  • option:checked — cible l’option actuellement sélectionnée

Avec base-select, vous pouvez styliser directement le dropdown picker, l’animer à l’ouverture et à la fermeture, et utiliser l’élément <selectedcontent> pour refléter le contenu de l’option sélectionnée dans le contrôle fermé. Les navigateurs supportant cette fonctionnalité permettent également un balisage plus riche à l’intérieur des options lorsque le modèle de select personnalisable est activé.

Support navigateur : actuellement limité principalement aux navigateurs basés sur Chromium. Vérifiez le statut actuel sur Can I Use.

Utilisez @supports pour l’appliquer comme amélioration progressive :

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

Quelle approche devriez-vous utiliser ?

appearance: noneappearance: base-select
Support navigateur95%+Limité (voir tableau de support)
Stylise le panneau déroulantNonOui
Contenu riche dans les optionsNonOui
AccessibilitéNativeNative

Utilisez la technique du conteneur avec appearance: none comme base de référence. Elle fonctionne partout, préserve l’accessibilité et vous donne un contrôle solide sur l’état fermé du select. Superposez appearance: base-select par-dessus avec @supports pour les navigateurs qui le supportent.

Conclusion

Personnaliser les menus déroulants HTML select avec CSS n’est plus un choix entre « contrôle total avec JavaScript » ou « accepter les paramètres par défaut du navigateur ». Le pattern de conteneur appearance: none reste la fondation cross-browser fiable, tandis que appearance: base-select ouvre la porte au stylage du panneau déroulant, à l’intégration de contenu plus riche dans les options et à l’animation du picker. L’écart entre ces deux extrêmes se réduit, mais pas encore uniformément sur tous les navigateurs. Commencez par la technique héritée, superposez progressivement la moderne, et vous couvrirez le plus large éventail d’utilisateurs avec le moins de friction.

FAQ

Non. Définir appearance: none ne fait que supprimer le stylage visuel fourni par le système d'exploitation. L'élément HTML select sous-jacent conserve tout le comportement clavier natif, y compris la navigation par touches fléchées, Entrée et Espace pour ouvrir le menu déroulant, et Tab pour déplacer le focus. Les lecteurs d'écran continuent d'annoncer correctement les options car la structure DOM reste inchangée.

Le support des éléments select personnalisables évolue encore et varie selon les navigateurs. Les navigateurs basés sur Chromium ont livré la fonctionnalité en premier, tandis que d'autres moteurs sont encore en train de l'implémenter. Vérifiez les dernières données de compatibilité sur caniuse.com avant de vous y fier en production, et enveloppez vos styles base-select dans un bloc @supports (appearance: base-select) afin que les navigateurs non supportés reviennent gracieusement à vos styles hérités.

L'élément select ignore de nombreuses propriétés CSS lorsqu'il est rendu nativement. Une div conteneur vous donne un contrôle total sur les bordures, border-radius, la couleur d'arrière-plan et la flèche personnalisée via un pseudo-élément. La technique de superposition grid empile la flèche au-dessus du select sans interférer avec les événements de clic, ce que vous ne pouvez pas réaliser sur le select seul.

Utilisez un pseudo-élément CSS sur le conteneur avec clip-path pour dessiner une forme de triangle purement en CSS. Définissez pointer-events à none sur le pseudo-élément pour que les clics passent à travers vers le select en dessous. Alternativement, vous pouvez utiliser un SVG inline comme background-image sur le conteneur, encodé en data URI pour éviter une requête réseau supplémentaire.

Truly understand users experience

See every user interaction, feel every frustration and track all hesitations with OpenReplay — the open-source digital experience platform. It can be self-hosted in minutes, giving you complete control over your customer data. . Check our GitHub repo and join the thousands of developers in our community..

OpenReplay