1495 votes

Comment styliser un menu déroulant <select> avec uniquement du CSS ?

Existe-t-il un moyen, uniquement en CSS, de donner du style à un fichier de type <select> dropdown ?

J'ai besoin de styliser un <select> autant qu'il est humainement possible, sans aucun JavaScript. Quelles sont les propriétés que je peux utiliser pour ce faire en CSS ?

Ce code doit être compatible avec tous les principaux navigateurs :

  • Internet Explorer 6, 7 et 8
  • Firefox
  • Safari

Je sais que je peux le faire avec JavaScript : Exemple .

Et je ne parle pas d'un simple style. Je veux savoir ce que l'on peut faire de mieux avec CSS uniquement.

J'ai trouvé questions similaires sur Stack Overflow.

Et celui-ci sur Doctype.com.

58 votes

Je pense que c'est une question légitime, mais la réponse est "non, pas vraiment" ou "pas comme vous le souhaitez". Mais personne (ni moi) n'en est sûr à 100%, ce sentiment d'ambiguïté s'insinue dans la peau du lecteur et la légitimité de la question est remise en question.

1 votes

@Jitendra, je sais où vous voulez en venir. Nous aimerions que vous rendiez votre question plus explicite. De plus, je pense avoir trouvé ce que vous cherchez. C'est expérimental, mais regardez ça : cappuccino.org/aristo/showcase

1 votes

@jeremyosborne - Merci pour la réponse. Je sais que je peux le faire avec javascript. Votre lien eaxmple est basé sur JS. J'ai posé cette question parce que je voulais savoir si quelqu'un sait ce que l'on peut faire de mieux avec css uniquement.

1138voto

Danield Points 17720

Voici trois solutions :

Solution #1 - appearance : none - avec la solution de contournement d'Internet Explorer 10 - 11 ( Démo )

--

Pour masquer le jeu de flèches par défaut appearance: none sur l'élément de sélection, puis ajoutez votre propre flèche personnalisée avec background-image

select {
   -webkit-appearance: none;
   -moz-appearance: none;
   appearance: none;       /* Remove default arrow */
   background-image: url(...);   /* Add custom arrow */
}

Support des navigateurs :

appearance: none offre un très bon support pour les navigateurs ( caniuse ) - sauf pour Internet Explorer.

Nous pouvons améliorer cette technique et ajouter le support pour Internet Explorer 10 et Internet Explorer 11 en ajoutant

select::-ms-expand {
    display: none; /* Hide the default arrow in Internet Explorer 10 and Internet Explorer 11 */
}

Si Internet Explorer 9 est un problème, nous n'avons aucun moyen de supprimer la flèche par défaut (ce qui signifierait que nous aurions maintenant deux flèches), mais nous pourrions utiliser un sélecteur Internet Explorer 9 funky.

Pour au moins annuler notre flèche personnalisée - en laissant intacte la flèche de sélection par défaut.

/* Target Internet Explorer 9 to undo the custom arrow */
@media screen and (min-width:0\0) {
    select {
        background-image:none\9;
        padding: 5px\9;
    }
}

Tous ensemble :

select {
  margin: 50px;
  width: 150px;
  padding: 5px 35px 5px 5px;
  font-size: 16px;
  border: 1px solid #CCC;
  height: 34px;
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  background: url(https://stackoverflow.com/favicon.ico) 96% / 15% no-repeat #EEE;
}

/* CAUTION: Internet Explorer hackery ahead */

select::-ms-expand {
    display: none; /* Remove default arrow in Internet Explorer 10 and 11 */
}

/* Target Internet Explorer 9 to undo the custom arrow */
@media screen and (min-width:0\0) {
    select {
        background: none\9;
        padding: 5px\9;
    }
}

<select>
  <option>Apples</option>
  <option selected>Pineapples</option>
  <option>Chocklate</option>
  <option>Pancakes</option>
</select>

Cette solution est facile et bénéficie d'une bonne prise en charge par les navigateurs - elle devrait généralement suffire.


Si la prise en charge du navigateur Internet Explorer est nécessaire, lisez ce qui suit.

Solution n°2 : tronquez l'élément de sélection pour masquer la flèche par défaut ( Démonstration )

--

(Lire la suite ici)

Enveloppez le select dans un div avec un largeur fixe et overflow:hidden .

Ensuite, donnez le select élément d'une largeur d'environ 20 pixels de plus que le div .

Le résultat est que la flèche déroulante par défaut de l'option select sera masqué (en raison de l'élément overflow:hidden sur le conteneur), et vous pouvez placer l'image d'arrière-plan de votre choix sur le côté droit de la division.

Le site avantage de cette approche est qu'elle est multi-navigateurs (Internet Explorer 8 et plus), WebKit et Gecko ). Cependant, le désavantage de cette approche est que la liste déroulante des options dépasse sur le côté droit (de 20 pixels que nous avons cachés... parce que les éléments d'option prennent la largeur de l'élément de sélection).

Enter image description here

Il convient toutefois de noter que si l'élément de sélection personnalisé n'est nécessaire que pour les éléments suivants mobile le problème ci-dessus ne se pose pas, car chaque téléphone ouvre l'élément de sélection de manière native. Donc, pour les mobiles, c'est peut-être la meilleure solution].

.styled select {
  background: transparent;
  width: 150px;
  font-size: 16px;
  border: 1px solid #CCC;
  height: 34px;
}
.styled {
  margin: 50px;
  width: 120px;
  height: 34px;
  border: 1px solid #111;
  border-radius: 3px;
  overflow: hidden;
  background: url(https://stackoverflow.com/favicon.ico) 96% / 20% no-repeat #EEE;
}

<div class="styled">
  <select>
    <option>Pineapples</option>
    <option selected>Apples</option>
    <option>Chocklate</option>
    <option>Pancakes</option>
  </select>
</div>

Si la flèche personnalisée est nécessaire sur Firefox - avant le Version 35 - mais vous n'avez pas besoin de prendre en charge les anciennes versions d'Internet Explorer - alors continuez à lire...

Solution n° 3 - Utilisez le pointer-events propriété ( Démonstration )

--

(Lire la suite ici)

L'idée ici est de superposer un élément sur la flèche déroulante native (pour créer notre flèche personnalisée) et d'interdire les événements de pointeur sur celle-ci.

Avantage : Il fonctionne bien dans WebKit et Gecko. Il est également très esthétique (pas de saillies). option éléments).

Inconvénient : Internet Explorer (Internet Explorer 10 et inférieur) ne prend pas en charge pointer-events ce qui signifie que vous ne pouvez pas cliquer sur la flèche personnalisée. En outre, un autre inconvénient (évident) de cette méthode est que vous ne pouvez pas cibler votre nouvelle image de flèche avec un effet de survol ou un curseur manuel, car nous venons de désactiver les événements de pointeur sur eux !

Toutefois, avec cette méthode, vous pouvez utiliser Modernizer ou des commentaires conditionnels pour qu'Internet Explorer revienne à la flèche standard intégrée.

NB : Étant donné qu'Internet Explorer 10 ne prend pas en charge conditional comments plus : Si vous voulez utiliser cette approche, vous devriez probablement utiliser Modernizr . Cependant, il est encore possible d'exclure le CSS "pointer-events" d'Internet Explorer 10 avec un hack CSS décrit ici .

.notIE {
  position: relative;
  display: inline-block;
}
select {
  display: inline-block;
  height: 30px;
  width: 150px;
  outline: none;
  color: #74646E;
  border: 1px solid #C8BFC4;
  border-radius: 4px;
  box-shadow: inset 1px 1px 2px #DDD8DC;
  background: #FFF;
}
/* Select arrow styling */

.notIE .fancyArrow {
  width: 23px;
  height: 28px;
  position: absolute;
  display: inline-block;
  top: 1px;
  right: 3px;
  background: url(https://stackoverflow.com/favicon.ico) right / 90% no-repeat #FFF;
  pointer-events: none;
}
/*target Internet Explorer 9 and Internet Explorer 10:*/

@media screen and (min-width: 0\0) {
  .notIE .fancyArrow {
    display: none;
  }
}

<!--[if !IE]> -->
<div class="notIE">
  <!-- <![endif]-->
  <span class="fancyArrow"></span>
  <select>
    <option>Apples</option>
    <option selected>Pineapples</option>
    <option>Chocklate</option>
    <option>Pancakes</option>
  </select>
  <!--[if !IE]> -->
</div>
<!-- <![endif]-->

1 votes

Laquelle de ces deux méthodes est la meilleure selon vous ?

3 votes

Cela dépend des exigences de conception. Si vous êtes d'accord pour que le menu déroulant soit en saillie, c'est la meilleure solution car elle est multi-navigateurs (IMO allbrowsers + IE8+ pourrait être considéré comme multi-navigateurs) mais je pense que pour beaucoup, cela ne suffira pas. En fait, dans ma déclaration ci-dessus, je voulais dire que l'approche n° 2 était la meilleure.

5 votes

De même, le bidule que j'ai posté utilise l'approche n° 2 avec des instructions conditionnelles pour permettre à IE d'utiliser sa flèche par défaut.

247voto

Matthew Morek Points 1895

C'est possible, mais malheureusement surtout dans les navigateurs basés sur WebKit, dans la mesure où nous, en tant que développeurs, en avons besoin. Voici un exemple de style CSS obtenu à partir du panneau d'options de Chrome via l'inspecteur d'outils de développement intégré, amélioré pour correspondre aux propriétés CSS actuellement prises en charge dans la plupart des navigateurs modernes :

select {
    -webkit-appearance: button;
    -moz-appearance: button;
    -webkit-user-select: none;
    -moz-user-select: none;
    -webkit-padding-end: 20px;
    -moz-padding-end: 20px;
    -webkit-padding-start: 2px;
    -moz-padding-start: 2px;
    background-color: #F07575; /* Fallback color if gradients are not supported */
    background-image: url(../images/select-arrow.png), -webkit-linear-gradient(top, #E5E5E5, #F4F4F4); /* For Chrome and Safari */
    background-image: url(../images/select-arrow.png), -moz-linear-gradient(top, #E5E5E5, #F4F4F4); /* For old Firefox (3.6 to 15) */
    background-image: url(../images/select-arrow.png), -ms-linear-gradient(top, #E5E5E5, #F4F4F4); /* For pre-releases of Internet Explorer  10*/
    background-image: url(../images/select-arrow.png), -o-linear-gradient(top, #E5E5E5, #F4F4F4); /* For old Opera (11.1 to 12.0) */
    background-image: url(../images/select-arrow.png), linear-gradient(to bottom, #E5E5E5, #F4F4F4); /* Standard syntax; must be last */
    background-position: center right;
    background-repeat: no-repeat;
    border: 1px solid #AAA;
    border-radius: 2px;
    box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1);
    color: #555;
    font-size: inherit;
    margin: 0;
    overflow: hidden;
    padding-top: 2px;
    padding-bottom: 2px;
    text-overflow: ellipsis;
    white-space: nowrap;
}

Lorsque vous exécutez ce code sur n'importe quelle page d'un navigateur basé sur WebKit, il devrait changer l'apparence de la boîte de sélection, supprimer la flèche OS standard et ajouter une flèche PNG, mettre un espace avant et après l'étiquette, presque tout ce que vous voulez.

La partie la plus importante est le appearance qui modifie le comportement de l'élément.

Il fonctionne parfaitement dans presque tous les navigateurs basés sur WebKit, y compris les navigateurs mobiles, bien que Gecko ne supporte pas appearance ainsi que WebKit, semble-t-il.

4 votes

Hé, j'ai remarqué que les boîtes de sélection ont commencé à avoir un aspect très différent à partir de Firefox 12 (elles ressemblent BEAUCOUP à celles de Chrome (j'ai un Mac)), et il semble que FF 12 supporte un tas d'attributs d'apparence supplémentaires.

0 votes

N'oubliez pas de définir les couleurs du fond ET du texte, chaque système d'exploitation étant différent. Si le système d'exploitation de l'utilisateur est gris (ce qui est très probable), ce numéro 555 sera presque invisible. Je vois ce problème partout sur le web.

3 votes

Une solution uniquement en chrome... Je ne paierais pas pour cela, ni mon client. Voir la réponse de @Dianeld pour une solution x-browser.

69voto

pavium Points 7845

L'élément select et sa fonction de liste déroulante sont difficile à coiffer.

attributs de style pour l'élément select par Chris Heilmann confirme ce que Ryan Dohery a dit dans un commentaire à la première réponse :

"L'élément select fait partie du système d'exploitation, et non du navigateur chrome. Par conséquent, il est très peu fiable pour le style, et il n'est pas forcément judicieux d'essayer de toute façon."

65voto

Henrik Helmers Points 952

J'avais exactement le même problème, sauf que je ne pouvais pas utiliser d'images et que je n'étais pas limité par le support du navigateur. Cela devrait être "conforme" et, avec un peu de chance, commencer à fonctionner partout. éventuellement .

Il utilise des couches d'arrière-plan tournées pour "découper" une flèche déroulante, car les pseudo-éléments ne fonctionneraient pas pour l'élément de sélection.

Edit : Dans cette version actualisée, j'utilise des variables CSS et un petit système de thématisation.

:root {
  --radius: 2px;
  --baseFg: dimgray;
  --baseBg: white;
  --accentFg: #006fc2;
  --accentBg: #bae1ff;
}

.theme-pink {
  --radius: 2em;
  --baseFg: #c70062;
  --baseBg: #ffe3f1;
  --accentFg: #c70062;
  --accentBg: #ffaad4;
}

.theme-construction {
  --radius: 0;
  --baseFg: white;
  --baseBg: black;
  --accentFg: black;
  --accentBg: orange;
}

select {
  font: 400 12px/1.3 sans-serif;
  -webkit-appearance: none;
  appearance: none;
  color: var(--baseFg);
  border: 1px solid var(--baseFg);
  line-height: 1;
  outline: 0;
  padding: 0.65em 2.5em 0.55em 0.75em;
  border-radius: var(--radius);
  background-color: var(--baseBg);
  background-image: linear-gradient(var(--baseFg), var(--baseFg)),
    linear-gradient(-135deg, transparent 50%, var(--accentBg) 50%),
    linear-gradient(-225deg, transparent 50%, var(--accentBg) 50%),
    linear-gradient(var(--accentBg) 42%, var(--accentFg) 42%);
  background-repeat: no-repeat, no-repeat, no-repeat, no-repeat;
  background-size: 1px 100%, 20px 22px, 20px 22px, 20px 100%;
  background-position: right 20px center, right bottom, right bottom, right bottom;   
}

select:hover {
  background-image: linear-gradient(var(--accentFg), var(--accentFg)),
    linear-gradient(-135deg, transparent 50%, var(--accentFg) 50%),
    linear-gradient(-225deg, transparent 50%, var(--accentFg) 50%),
    linear-gradient(var(--accentFg) 42%, var(--accentBg) 42%);
}

select:active {
  background-image: linear-gradient(var(--accentFg), var(--accentFg)),
    linear-gradient(-135deg, transparent 50%, var(--accentFg) 50%),
    linear-gradient(-225deg, transparent 50%, var(--accentFg) 50%),
    linear-gradient(var(--accentFg) 42%, var(--accentBg) 42%);
  color: var(--accentBg);
  border-color: var(--accentFg);
  background-color: var(--accentFg);
}

<select>
  <option>So many options</option>
  <option>...</option>
</select>

<select class="theme-pink">
  <option>So many options</option>
  <option>...</option>
</select>

<select class="theme-construction">
  <option>So many options</option>
  <option>...</option>
</select>

6 votes

Wow, c'est l'une des solutions les plus cool que j'ai vues. Elle fonctionne pour moi dans les dernières versions de Chrome et Safari sur Mac. Qu'en est-il des autres navigateurs ?

2 votes

Cela fonctionne pour moi dans firefox avec l'ajout de -moz-appearance: none;

0 votes

Bonjour @Henrik, Pour le rose, comment puis-je faire en sorte que la partie principale (la partie avec tant d'options) change de couleur avec un gradient linéaire ? Je veux que cette partie principale ait aussi une couleur multiple comme ceci : background-image: linear-gradient(to right, #a1c4fd 0%, #c2e9fb 51%, #a1c4fd 100%); }

46voto

ioTus Points 406

La plus grande incohérence que j'ai remarquée dans le style des listes déroulantes de sélection est la suivante Safari et Google Chrome (Firefox est entièrement personnalisable grâce aux CSS). Après quelques recherches dans les profondeurs obscures de l'Internet, je suis tombé sur ce qui suit, qui résout presque complètement mes problèmes avec WebKit :

Correction pour Safari et Google Chrome :

select {
  -webkit-appearance: none;
}

Toutefois, cela supprime la flèche déroulante. Vous pouvez ajouter une flèche déroulante à l'aide d'une commande voisine div avec un arrière-plan, une marge négative ou un positionnement absolu sur la liste déroulante de sélection.

*Plus d'informations et d'autres variables sont disponibles dans Propriété CSS : -webkit-appearance .

1 votes

N'oubliez pas d'ajouter votre style après cela ;) Mais je suis très heureux d'avoir lu ce commentaire aujourd'hui.

1 votes

Pouvez-vous s'il vous plaît élaborer sur votre déclaration : "Firefox est entièrement personnalisable grâce aux CSS". Pour moi, il semble que Firefox ne prenne pas en charge la propriété "Apparence"... alors comment faire dans Firefox ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X