Styles de sélection personnalisés avec CSS pur

Ceci est l’épisode 20 d’une série examinant les solutions CSS modernes aux problèmes que j’ai résolus depuis plus de 13 ans en tant que développeur frontend.

Le CSS moderne nous donne une gamme de propriétés pour obtenir des styles de sélection personnalisés qui ont un apparence initiale des éléments select uniques, multiples et désactivés dans les principaux navigateurs.

Quelques propriétés et techniques que notre solution utilisera:

  • clip-path pour créer la flèche déroulante personnalisée
  • disposition de la grille CSS pour aligner la sélection native et la flèche
  • variables CSS personnalisées pour style flexible
  • em unités pour le dimensionnement relatif

Problèmes courants avec les sélections natives #

Comme pour tous les types de champs de formulaire, <select> varie dun navigateur à lautre dans son apparence initiale.

De gauche à droite, voici lapparence initiale de <select> dans Firefox, Chrome et Safari:

Les différences incluent la taille de la boîte, la taille de la police, la hauteur de la ligne, et le plus remarquable est la différence de style de lindicateur de liste déroulante.

Notre Lobjectif est de créer la même apparence initiale dans ces navigateurs, y compris plusieurs sélections et des états désactivés.

Remarque: la liste déroulante nest toujours pas stylable, donc une fois que le <select> est ouvert, il reprendra les styles du navigateur individuel pour la liste option. Cest correct – nous pouvons gérer cela pour conserver laccessibilité gratuite dune sélection native!

HTML de base #

Nous  » Nous allons nous concentrer sur un seul <select> pour commencer.

Le libellé ne fait pas partie de notre exercice de style, mais il est inclus comme exigence générale, notamment avec le for attribut ayant la valeur de id sur le <select>.

Pour réaliser nos styles personnalisés, nous « avons enveloppé la sélection native dans un div supplémentaire avec la classe select pour plus de simplicité dans ce didacticiel.

Réinitialiser et supprimer les styles hérités #

Comme cela est inclus dans tous mes tutoriels en tant que meilleure pratique moderne, nous ajoutons dabord la réinitialisation suivante:

Ensuite, nous pouvons commencer la règle pour le select natif et appliquer ce qui suit pour faire reposer son apparence:

Bien que la plupart de ceux-ci soient probablement familiers, le sort bizarre est . Cest une propriété rarement utilisée et vous noterez que ce nest pas tout à fait là où nous « voudrions quelle pour le support, mais ce quelle nous fournit principalement dans ce cas est la suppression de la flèche de déroulement du navigateur natif.

Remarque: Le CodePen est configuré pour utiliser un autoprefixer qui ajoutera les versions pré-fixes requises de la propriété appearance. Vous devrez peut-être le configurer spécifiquement pour votre projet ou les ajouter manuellement. Mon HTML / Sass Jumpstart inclut un préfixeur automatique dans le cadre de la version de production.

La bonne nouvelle est que nous pouvons ajouter une règle supplémentaire pour obtenir la suppression de la flèche pour les versions inférieures dIE si vous en avez besoin:

Cette astuce se trouve dans le excellent article de Filament Group qui montre une autre méthode pour créer des styles sélectionnés.

La dernière partie consiste à supprimer la valeur par défaut outline. Ne vous inquiétez pas – nous  » Jajouterai un remplacement plus tard pour le :focus état!

Et voici un gif de nos progrès. Vous pouvez voir quil ny a maintenant aucune indication visuelle indiquant quil sagit dun select avant de cliquer dessus:

Styles de boîte de sélection personnalisée #

Commençons par configurer quelques variables CSS. Cela permettra à notre sélection dêtre re-colorée de manière flexible, de manière à représenter un état derreur.

Note daccessibilité: en tant quélément dinterface utilisateur, la bordure de sélection doit avoir un contraste de 3: 1 ou supérieur à la couleur de la surface environnante.

Il est maintenant temps de créer les styles de sélection personnalisés que nous appliquerons à notre habillage div.select:

Tout dabord, nous mettons en place des contraintes de largeur. Les valeurs min-width et max-width sont principalement destinées à cette démo, et vous pouvez choisir de la supprimer ou de la modifier en fonction de votre cas dutilisation.

Ensuite, nous appliquons certaines propriétés de modèle de boîte, notamment border, border-radius et padding. Notez lutilisation de lunité em qui gardera ces propriétés proportionnelles à lensemble font-size.

Dans les styles de réinitialisation, nous définissons plusieurs propriétés sur inherit, nous définissons donc ici celles-ci, y compris font-size, cursor, et line-height.

Enfin, nous lui fournissons des propriétés darrière-plan, y compris un dégradé pour le moindre de dimension. Si vous supprimez les propriétés darrière-plan, la sélection sera transparente et ramassera larrière-plan de la page. Ceci peut être souhaitable, cependant, soyez conscient et testez les effets sur le contraste.

Et voici notre progression:

Personnalisé Sélectionnez la flèche déroulante #

Pour notre flèche déroulante, nous allons utiliser lune des propriétés CSS modernes les plus intéressantes: clip-path.

Les chemins de clip nous permettent de créer toutes sortes de formes en « coupant » les formes carrées et rectangulaires que nous recevons par défaut de la plupart des éléments. Je me suis amusé à utiliser clip-path sur ma récente refonte du site portfolio.

Avant clip-path avoir un meilleur support, méthodes alternatives incluses:

  • background-image – typiquement un png, légèrement plus moderne serait un SVG
  • un SVG en ligne comme élément supplémentaire
  • lastuce de bordure pour créer un triangle

SVG peut sembler être la solution optimale, mais lorsquil est utilisé comme background-image, il perd la capacité dagir comme une icône dans le sens de ne pas pouvoir t o modifier ses propriétés telles que la couleur de remplissage sans la redéfinir entièrement. Cela signifie que nous ne pouvons pas utiliser notre variable personnalisée CSS.

Placer un SVG en ligne résout le problème de couleur fill, mais cela signifie inclure un élément supplémentaire à chaque fois quun <select> est défini.

Avec clip-path, nous obtenons un « graphique » de flèche net et évolutif qui ressemble à un SVG mais avec les avantages de pouvoir utiliser notre variable personnalisée et dêtre contenue dans le style par rapport au balisage HTML.

Pour créer la flèche, nous la définirons comme ::after pseudo-élément.

La syntaxe clip-path est un peu étrange, et puisquelle « s pas vraiment le sujet de cet article, je recommande les ressources suivantes:

  • Colby Fayock explique la syntaxe avec un exemple dans cette vidéo à tête-à-tête
  • Clippy est un outil en ligne qui permet vous permet de sélectionner une forme et dajuster les points tout en générant dynamiquement le clip-path CSS

Si vous « suivez aile le long, vous avez peut-être remarqué que la flèche napparaît pas malgré la définition de width et height. Une fois inspecté, il a été constaté que le ::after nest pas autorisé à sa largeur.

Nous allons résoudre ce problème en mettant à jour notre .select pour utiliser la disposition de la grille CSS.

Cela permet à la flèche dapparaître en lui étendant essentiellement une valeur daffichage semblable à « block ».

À ce stade, nous pouvons vérifier que nous avons bien créé un triangle.

Pour corriger lalignement, nous allons utiliser mon hack de grille CSS préféré (vieux chapeau si vous avez lu quelques articles ici!).

Ancienne solution CSS: position: absolute Nouvelle solution CSS: Un seul grid-template-areas pour les contenir tous

Nous allons dabord définir notre zone, puis définir que le select et ::after lutilisent tous les deux. Le nom est limité à lélément pour lequel il a été créé, et nous « allons le garder facile en lappelant » select « :

Ce qui nous donne un chevauchement de la flèche au-dessus de la sélection native en raison du contexte dempilement via lordre source:

Nous pouvons maintenant utiliser les propriétés de la grille pour finaliser lalignement de chaque élément:

Ta-da!

: focus State #

Oh oui – rappelez-vous comment nous avons supprimé le outline? Nous devons résoudre le :focus de laisser tomber cela.

Il y a une propriété à venir que nous pourrions utiliser appelée :focus-within mais il est toujours préférable dinclure un polyfill pour cela à ceci

Pour ce didacticiel, nous utiliserons une autre méthode permettant d’obtenir le même résultat, juste un peu plus lourd.

Malheureusement, cela signifie que nous devons ajouter un élément supplémentaire dans le DOM.

Après lélément de sélection natif, comme le dernier enfant dans .select, ajoutez:

Pourquoi après? Parce que comme il sagit dune solution CSS pure, la placer après la sélection native signifie que nous pouvons la modifier lorsque select est ciblé en utilisant le sélecteur frère adjacent – +.

Cela nous permet de créer la règle suivante:

Vous vous demandez peut-être pourquoi nous » revenons à position: absolute après avoir simplement appris le hack précédent de grid-area.

La raison est déviter de recalculer les ajustements basés sur le remplissage. Si vous l’essayez vous-même, vous verrez que même si vous définissez width et height sur 100%, il reste dans le remplissage .

Le travail que position: absolute fait le mieux est de faire correspondre la taille dun élément. Nous « tirons un pixel supplémentaire dans chaque direction pour nous assurer quil chevauche la bordure propriété.

Mais, nous devons faire un ajout supplémentaire à .select pour nous assurer quil « est relatif à notre sélection par – eh bien, position: relative.

Et voici notre sélection personnalisée tous ensemble comme on le voit dans Chrome:

Sélection multiple #

Les sélections viennent dans une seconde saveur, qui permet à un utilisateur de sélectionner plus dune option. Du point de vue HTML, cela signifie simplement ajouter lattribut multiple, mais nous ajouterons également une classe pour aider à créer des ajustements de style appelée select--multiple :

Et en le regardant, nous pouvons voir quil a hérité de la plupart de nos styles favorablement, sauf que nous navons pas besoin de la flèche dans cette vue.

Il sagit dune solution rapide pour ajuster notre sélecteur qui définit la flèche. Nous utilisons :not() pour exclure notre nouvelle classe définie:

Nous avons quelques ajustements mineurs à faire pour la sélection multiple, le premier consiste à supprimer le remplissage qui a été précédemment ajouté pour faire de la place pour la flèche:

Par défaut, les options avec une valeur longue déborderont de la zone visible et seront coupées, mais jai trouvé que les principaux navigateurs permettent de remplacer le wrapping si vous le souhaitez:

En option, nous pouvons définir un height sur la sélection pour apporter un comportement cross-browser un peu plus fiable. En testant cela, jai appris que Chrome et Firefox afficheraient une option partielle, mais Safari masquera complètement une option qui ne peut pas être entièrement visible.

La hauteur doit être définie directement sur la sélection native . Compte tenu de nos autres styles, la valeur 6rem pourra afficher 3 options:

À ce stade, en raison de la compatibilité actuelle des navigateurs, nous avons effectué autant dajustements que possible.

Létat de :selected du options est assez personnalisable dans Chrome, un peu dans Firefox, et pas du tout dans Safari. Voir la démo de CodePen pour une section qui peut être supprimée pour prévisualiser ceci.

: styles désactivés #

Bien que je préconise ne montrant tout simplement pas les commandes désactivées, nous devrions préparer les styles pour cet état juste pour couvrir nos bases.

Pour accentuer létat désactivé, nous voulons appliquer un arrière-plan grisé. Mais comme nous « avons défini des styles darrière-plan sur .select et quil ny a pas de sélecteur » ta :parent, nous devons créer une dernière classe à gérer pour cet état:

Ici, nous avons « mis à jour le curseur comme un indice supplémentaire avec lequel le champ ne peut pas interagir, et mis à jour les valeurs darrière-plan que nous avions précédemment définies être blanc pour être maintenant plus gris pour létat désactivé.

Il en résulte les apparences suivantes:

Démo #

Vous pouvez le tester par vous-même, mais voici « un aperçu de la solution complète sur (de gauche) Firefox, Chrome et Safari:

Par Stephanie Eckles (@ 5t3ph)

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *