Comment puis-je styliser une liste déroulante <select> avec seulement CSS?

1333

Existe-t-il un moyen CSS uniquement de <select> liste déroulante?

J'ai besoin de styliser un <select>formulaire autant que possible, sans JavaScript. Quelles sont les propriétés que je peux utiliser pour le 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 de style simple. Je veux savoir ce que nous pouvons faire de mieux avec CSS uniquement.

J'ai trouvé des questions similaires sur Stack Overflow.

Et celui-ci sur Doctype.com.

Jitendra Vyas
la source
1
rien de bien trouvé sur google uniquement la solution js est là
Jitendra Vyas
41
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é se glisse sous la peau du lecteur et la légitimité de la question est remise en question.
ZJR
1
@Jitendra, je sais où tu veux en venir. Nous serions ravis que vous rendiez votre question plus explicite. De plus, je pense avoir trouvé ce que vous cherchez. C'est expérimental, mais vérifiez-le: cappuccino.org/aristo/showcase
jeremyosborne
1
@jeremyosborne - Merci pour la réponse. Je sais que je peux le faire avec javascript. votre lien simple est basé sur JS. Pourquoi j'ai posé cette question parce que je voulais savoir, est-ce que tout le monde sait ce que nous pouvons faire de mieux avec CSS uniquement
Jitendra Vyas
@Jitendra Merci d'avoir mis à jour votre question. Le mieux que vous puissiez faire de manière fiable avec les contraintes que vous avez (CSS uniquement et pas de JS) est de modifier la police (police), les couleurs d'arrière-plan et de premier plan (texte), la taille de la bordure, l'apparence et les couleurs, le placement et la taille (généralement via le type réglage via la police). Même alors, vous devrez probablement faire quelques ajustements pour vous assurer que les choses se ressemblent sur tous les navigateurs. J'aimerais avoir une meilleure réponse que cela, et peut-être en ai-je manqué une, mais je ne pense pas.
jeremyosborne

Réponses:

1028

Voici trois solutions:

Solution n ° 1 - apparence: aucune - avec solution de contournement d'Internet Explorer 10-11 ( démo )

-

Pour masquer la flèche par défaut définie appearance: nonesur l'élément de sélection, puis ajoutez votre propre flèche personnalisée avecbackground-image

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

Prise en charge du navigateur:

appearance: nonea une très bonne prise en charge du navigateur ( caniuse ) - sauf pour Internet Explorer 11 (et versions ultérieures) et Firefox 34 (et versions ultérieures).

Nous pouvons améliorer cette technique et ajouter la prise en charge d'Internet Explorer 10 et d'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 génial d'Internet Explorer 9.

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:

Cette solution est simple et prend en charge un bon navigateur - elle devrait généralement suffire.


Si la prise en charge du navigateur pour Internet Explorer 9 (et versions ultérieures) et Firefox 34 (et versions ultérieures) est nécessaire, continuez à lire ...

Solution # 2 Tronquez l'élément de sélection pour masquer la flèche par défaut ( démo )

-

(En savoir plus ici)

Enveloppez l' selectélément dans un div avec une largeur fixe etoverflow:hidden .

Donnez ensuite à l' selectélément une largeur d'environ 20 pixels supérieure à la div .

Le résultat est que la flèche déroulante par défaut de l' selectélément sera masquée (en raison de laoverflow:hidden sur le conteneur), et vous pouvez placer n'importe quelle image d'arrière-plan que vous voulez sur le côté droit de la div.

L' avantage de cette approche est qu'elle est multi-navigateur (Internet Explorer 8 et versions ultérieures, WebKit et Gecko ). Cependant, l' inconvénient de cette approche est que la liste déroulante des options dépasse du côté droit (par les 20 pixels que nous avons cachés ... car les éléments d'option prennent la largeur de l'élément de sélection).

Entrez la description de l'image ici

[Il convient toutefois de noter que si l'élément de sélection personnalisé n'est nécessaire que pour les appareils mobiles - le problème ci-dessus ne s'applique pas - en raison de la façon dont chaque téléphone ouvre nativement l'élément de sélection. Donc, pour les mobiles, cela peut être la meilleure solution.]


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

Solution # 3 - Utilisez la pointer-eventspropriété ( démo )

-

(En savoir plus ici)

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

Avantage: il fonctionne bien dans WebKit et Gecko. Il a l'air bien aussi (pas d' optionéléments saillants ).

Inconvénient: Internet Explorer (Internet Explorer 10 et versions ultérieures) ne prend pas en chargepointer-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!

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

NB: Étant donné qu'Internet Explorer 10 ne prend conditional commentsplus en charge : Si vous souhaitez utiliser cette approche, vous devriez probablement utiliser Modernizr . Cependant, il est toujours possible d'exclure le CSS des événements de pointeur d'Internet Explorer 10 avec un hack CSS décrit ici .

Danield
la source
1
Laquelle est la meilleure selon vous à partir de ces 2 méthodes?
Jitendra Vyas
3
Cela dépend des exigences de conception. Si vous êtes d'accord avec le menu déroulant - alors c'est le meilleur car il s'agit d'un navigateur croisé (tous les navigateurs IMO + IE8 + pourraient être considérés comme un navigateur croisé) mais je pense que pour beaucoup - cela ne fonctionnera pas. Donc, en fait, dans ma déclaration ci-dessus, je voulais dire que l'approche # 2 était la meilleure.
Danield
4
De plus, le violon que j'ai posté utilise l'approche # 2 avec des instructions conditionnelles pour permettre à IE d'utiliser sa flèche par défaut.
Danield
3
@AlexisLeclerc Fixer le div et sélectionner à la même largeur ne fonctionne que dans les navigateurs -webkit comme Chrome. (parce que j'ai inclus la règle - apparence webkit: aucune; ) Cependant, cela ne fonctionne pas dans d'autres navigateurs comme firefox
Danield
4
Si je peux proposer une amélioration pour l'approche n ° 1, je trouve personnellement le manque de frontière ou le manque de halo de sélection du côté droit très agaçant. J'ai mis à jour votre violon avec quelque chose que j'ai utilisé dans mon projet actuel: jsfiddle.net/YvCHW/1745 . Dis-moi ce que tu penses!
Alexis Leclerc
233

C'est possible, mais malheureusement surtout dans les navigateurs WebKit dans la mesure où nous, en tant que développeurs, l'exige. Voici l'exemple du style CSS collecté à partir du panneau d'options Chrome via l'inspecteur des 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 WebKit, il doit modifier l'apparence de la zone de sélection, supprimer la flèche OS standard et ajouter une flèche PNG, mettre un peu d'espacement avant et après l'étiquette, presque tout ce que vous voulez.

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

Il fonctionne parfaitement dans presque tous les navigateurs WebKit, y compris les mobiles, bien que Gecko ne supporte pas appearanceaussi bien que WebKit, semble-t-il.

Matthew Morek
la source
4
Hé, j'ai remarqué que les boîtes de sélection commençaient à être très différentes à partir de Firefox 12 (cela ressemble beaucoup à Chrome (j'ai un Mac)), et il semble que FF 12 supporte un tas plus d'attributs d'apparence.
CWSpear
3
une solution uniquement pour le chrome ... Je ne paierais pas cela, ni mon client. voir la réponse de @ Dianeld pour une solution x-browser.
Adrien Be
41
@AdrienBe Ma solution a été proposée il y a près de 3 ans; à l'époque, c'était le seul moyen raisonnable de relooker des boîtes de sélection sans impliquer de bibliothèques ou de plugins JavaScript. C'est toujours viable si vous décidez de supprimer les attributs préfixés, mais cela ne fonctionne de manière fiable que dans les navigateurs Webkit (donc Safari, nouvel Opera + Android également). À l'heure actuelle, il existe peut-être de meilleures solutions. Au lieu d'ajouter des commentaires dénués de sens, votez simplement pour la solution que vous jugez meilleure et vérifiez à l'avenir la date de "réponse". Merci.
Matthew Morek
4
@MatthewMorek: il y avait une meilleure solution, il y a même 3 ans. La réponse de Daniel est bien meilleure en ce qui concerne la prise en charge de plusieurs navigateurs (elle prend en charge IE8 et versions ultérieures, WebKit et Gecko). La question demandait "le code doit être compatible avec tous les principaux navigateurs: Internet Explorer 6,7 et 8, Firefox & Safari". Cette exigence de navigateur x peut avoir été ajoutée par Paul Sweatte en 2013, bien que ... désolé si c'est le cas.
Adrien Be
3
Si vous ajoutez text-indent: 0.01px; text-overflow: "";cela fonctionnera encore mieux
Ivan
64

L'élément de sélection et sa fonction de liste déroulante sont difficiles à styliser.

Les attributs de style pour l'élément sélectionné par Chris Heilmann confirment 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, pas du chrome du navigateur. Par conséquent, il n'est pas très fiable de styliser, et il n'est pas nécessairement logique d'essayer de toute façon."

pavium
la source
47

J'ai eu ce problème exact, sauf que je ne pouvais pas utiliser d'images et n'était pas limité par la prise en charge du navigateur. Cela devrait être «selon les spécifications» et avec de la chance commencer à travailler partout éventuellement .

Il utilise des calques d'arrière-plan en couches pour «découper» une flèche déroulante, car les pseudo-éléments ne fonctionneraient pas pour l'élément sélectionné.

Edit: Dans cette version mise à jour, j'utilise des variables CSS et un petit système de thème.

: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>

Henrik
la source
5
Wow, c'est l'une des solutions les plus cool que j'ai vues. Cela fonctionne pour moi dans les dernières versions de Chrome et Safari sur Mac. Et les autres navigateurs?
Tintin81
2
Fonctionne pour moi dans Firefox avec l'ajout de-moz-appearance: none;
Zac
45

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

Correctif pour Safari et Google Chrome :

select {
  -webkit-appearance: none;
}

Cependant, cela supprime la flèche déroulante. Vous pouvez ajouter une flèche déroulante en utilisant une proximité divavec un arrière-plan, une marge négative ou absolument positionnée sur la liste déroulante sélectionnée.

* Plus d'informations et d'autres variables sont disponibles dans la propriété CSS: -webkit-apparence .

ioTus
la source
1
N'oubliez pas d'ajouter votre style après cela;) Mais je suis très heureux d'avoir lu ce commentaire aujourd'hui.
teewuane
1
pourriez-vous s'il vous plaît développer votre déclaration: "Firefox est entièrement personnalisable via CSS" pour moi, il semble que firefox ne supporte pas la propriété d'apparence ... alors comment cela serait-il fait dans firefox?
Danield
36

<select>les balises peuvent être stylisées via CSS comme tout autre élément HTML sur une page HTML rendue dans un navigateur. Voici un exemple (trop simple) qui positionnera un élément de sélection sur la page et rendra le texte des options en bleu.

Exemple de fichier HTML (selectExample.html):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
  <title>Select Styling</title>
  <link href="selectExample.css" rel="stylesheet">
</head>
<body>
<select id="styledSelect" class="blueText">
  <option value="apple">Apple</option>
  <option value="orange">Orange</option>
  <option value="cherry">Cherry</option>
</select>
</body>
</html>

Exemple de fichier CSS (selectExample.css):

/* All select elements on page */
select {
  position: relative;
}

/* Style by class. Effects the text of the contained options. */
.blueText {
  color: #0000FF;
}

/* Style by id. Effects position of the select drop down. */
#styledSelect {
  left: 100px;
}
jeremyosborne
la source
30
Incroyable, la première fois que j'ai vu des "mères" impliquées sur Internet sans que ce soit impoli. +1 pour ça!
BaL
34
Cette réponse ne résout pas cette question. Il ne sélectionne que les entrées, mais pas la liste déroulante
Kyborek
14
Cette réponse ignore totalement les défis liés au style d'une liste déroulante pour la cohérence entre les navigateurs. Il s'agit d'une réponse à très faible effort.
BentOnCoding
18

Le billet de blog Comment créer un formulaire déroulant CSS, aucun JavaScript ne fonctionne pour moi, mais il échoue dans Opera cependant:

select {
  border: 0 none;
  color: #FFFFFF;
  background: transparent;
  font-size: 20px;
  font-weight: bold;
  padding: 2px 10px;
  width: 378px;
  *width: 350px;
  *background: #58B14C;
}

#mainselection {
  overflow: hidden;
  width: 350px;
  -moz-border-radius: 9px 9px 9px 9px;
  -webkit-border-radius: 9px 9px 9px 9px;
  border-radius: 9px 9px 9px 9px;
  box-shadow: 1px 1px 11px #330033;
  background: url("arrow.gif") no-repeat scroll 319px 5px #58B14C;
}
<div id="mainselection">
  <select>
    <option>Select an Option</option>
    <option>Option 1</option>
    <option>Option 2</option>
  </select>
</div>

Daniel
la source
17

Voici une version qui fonctionne dans tous les navigateurs modernes. La clé utilise appearance:nonece qui supprime la mise en forme par défaut. Puisque tout le formatage a disparu, vous devez ajouter de nouveau dans la flèche qui différencie visuellement la sélection de l'entrée.

Exemple de travail: https://jsfiddle.net/gs2q1c7p/

select:not([multiple]) {
    -webkit-appearance: none;
    -moz-appearance: none;
    background-position: right 50%;
    background-repeat: no-repeat;
    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAMCAYAAABSgIzaAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDZFNDEwNjlGNzFEMTFFMkJEQ0VDRTM1N0RCMzMyMkIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDZFNDEwNkFGNzFEMTFFMkJEQ0VDRTM1N0RCMzMyMkIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0NkU0MTA2N0Y3MUQxMUUyQkRDRUNFMzU3REIzMzIyQiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0NkU0MTA2OEY3MUQxMUUyQkRDRUNFMzU3REIzMzIyQiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PuGsgwQAAAA5SURBVHjaYvz//z8DOYCJgUxAf42MQIzTk0D/M+KzkRGPoQSdykiKJrBGpOhgJFYTWNEIiEeAAAMAzNENEOH+do8AAAAASUVORK5CYII=);
    padding: .5em;
    padding-right: 1.5em
}

#mySelect {
    border-radius: 0
}
<select id="mySelect">
    <option>Option 1</option>
    <option>Option 2</option>
</select>

Eric
la source
16

Je suis arrivé à votre cas en utilisant Bootstrap . C'est la solution la plus simple qui fonctionne:

select.form-control {
    -moz-appearance: none;
    -webkit-appearance: none;
    appearance: none;
    background-position: right center;
    background-repeat: no-repeat;
    background-size: 1ex;
    background-origin: content-box;
    background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmVyc2lvbj0iMS4xIgogICBpZD0ic3ZnMiIKICAgdmlld0JveD0iMCAwIDM1Ljk3MDk4MyAyMy4wOTE1MTgiCiAgIGhlaWdodD0iNi41MTY5Mzk2bW0iCiAgIHdpZHRoPSIxMC4xNTE4MTFtbSI+CiAgPGRlZnMKICAgICBpZD0iZGVmczQiIC8+CiAgPG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhNyI+CiAgICA8cmRmOlJERj4KICAgICAgPGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPgogICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PgogICAgICAgIDxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz4KICAgICAgICA8ZGM6dGl0bGU+PC9kYzp0aXRsZT4KICAgICAgPC9jYzpXb3JrPgogICAgPC9yZGY6UkRGPgogIDwvbWV0YWRhdGE+CiAgPGcKICAgICB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMjAyLjAxNDUxLC00MDcuMTIyMjUpIgogICAgIGlkPSJsYXllcjEiPgogICAgPHRleHQKICAgICAgIGlkPSJ0ZXh0MzMzNiIKICAgICAgIHk9IjYyOS41MDUwNyIKICAgICAgIHg9IjI5MS40Mjg1NiIKICAgICAgIHN0eWxlPSJmb250LXN0eWxlOm5vcm1hbDtmb250LXdlaWdodDpub3JtYWw7Zm9udC1zaXplOjQwcHg7bGluZS1oZWlnaHQ6MTI1JTtmb250LWZhbWlseTpzYW5zLXNlcmlmO2xldHRlci1zcGFjaW5nOjBweDt3b3JkLXNwYWNpbmc6MHB4O2ZpbGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MTtzdHJva2U6bm9uZTtzdHJva2Utd2lkdGg6MXB4O3N0cm9rZS1saW5lY2FwOmJ1dHQ7c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1vcGFjaXR5OjEiCiAgICAgICB4bWw6c3BhY2U9InByZXNlcnZlIj48dHNwYW4KICAgICAgICAgeT0iNjI5LjUwNTA3IgogICAgICAgICB4PSIyOTEuNDI4NTYiCiAgICAgICAgIGlkPSJ0c3BhbjMzMzgiPjwvdHNwYW4+PC90ZXh0PgogICAgPGcKICAgICAgIGlkPSJ0ZXh0MzM0MCIKICAgICAgIHN0eWxlPSJmb250LXN0eWxlOm5vcm1hbDtmb250LXZhcmlhbnQ6bm9ybWFsO2ZvbnQtd2VpZ2h0Om5vcm1hbDtmb250LXN0cmV0Y2g6bm9ybWFsO2ZvbnQtc2l6ZTo0MHB4O2xpbmUtaGVpZ2h0OjEyNSU7Zm9udC1mYW1pbHk6Rm9udEF3ZXNvbWU7LWlua3NjYXBlLWZvbnQtc3BlY2lmaWNhdGlvbjpGb250QXdlc29tZTtsZXR0ZXItc3BhY2luZzowcHg7d29yZC1zcGFjaW5nOjBweDtmaWxsOiMwMDAwMDA7ZmlsbC1vcGFjaXR5OjE7c3Ryb2tlOm5vbmU7c3Ryb2tlLXdpZHRoOjFweDtzdHJva2UtbGluZWNhcDpidXR0O3N0cm9rZS1saW5lam9pbjptaXRlcjtzdHJva2Utb3BhY2l0eToxIj4KICAgICAgPHBhdGgKICAgICAgICAgaWQ9InBhdGgzMzQ1IgogICAgICAgICBzdHlsZT0iZmlsbDojMzMzMzMzO2ZpbGwtb3BhY2l0eToxIgogICAgICAgICBkPSJtIDIzNy41NjY5Niw0MTMuMjU1MDcgYyAwLjU1ODA0LC0wLjU1ODA0IDAuNTU4MDQsLTEuNDczMjIgMCwtMi4wMzEyNSBsIC0zLjcwNTM1LC0zLjY4MzA0IGMgLTAuNTU4MDQsLTAuNTU4MDQgLTEuNDUwOSwtMC41NTgwNCAtMi4wMDg5MywwIEwgMjIwLDQxOS4zOTM0NiAyMDguMTQ3MzIsNDA3LjU0MDc4IGMgLTAuNTU4MDMsLTAuNTU4MDQgLTEuNDUwODksLTAuNTU4MDQgLTIuMDA4OTMsMCBsIC0zLjcwNTM1LDMuNjgzMDQgYyAtMC41NTgwNCwwLjU1ODAzIC0wLjU1ODA0LDEuNDczMjEgMCwyLjAzMTI1IGwgMTYuNTYyNSwxNi41NDAxNyBjIDAuNTU4MDMsMC41NTgwNCAxLjQ1MDg5LDAuNTU4MDQgMi4wMDg5MiwwIGwgMTYuNTYyNSwtMTYuNTQwMTcgeiIgLz4KICAgIDwvZz4KICA8L2c+Cjwvc3ZnPgo=");
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<section class="container">
  <form class="form-horizontal">
    <select class="form-control">
      <option>One</option>
      <option>Two</option>
    </select>
  </form>
</section>

Remarque: le truc base64 est fa-chevron-downen SVG.

Yajo
la source
12

Dans les navigateurs modernes, le style <select>CSS est relativement indolore . Avec appearance: nonela seule partie délicate est de remplacer la flèche (si c'est ce que vous voulez). Voici une solution qui utilise un data:URI en ligne avec SVG en texte brut:

select {
  -moz-appearance: none;
  -webkit-appearance: none;
  appearance: none;
  
  background-repeat: no-repeat;
  background-size: 0.5em auto;
  background-position: right 0.25em center;
  padding-right: 1em;
  
  background-image: url("data:image/svg+xml;charset=utf-8, \
    <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 40'> \
      <polygon points='0,0 60,0 30,40' style='fill:black;'/> \
    </svg>");
}
<select>
  <option>Option 1</option>
  <option>Option 2</option>
</select>

<select style="font-size: 2rem;">
  <option>Option 1</option>
  <option>Option 2</option>
</select>

Le reste du style (bordures, rembourrage, couleurs, etc.) est assez simple.

Cela fonctionne dans tous les navigateurs que je viens d'essayer (Firefox 50, Chrome 55, Edge 38 et Safari 10). Une remarque à propos de Firefox est que si vous souhaitez utiliser le #caractère dans l'URI de données (par exemple fill: #000), vous devez l'échapper ( fill: %23000).

Kevin Christopher Henry
la source
1
Vous pouvez également dimensionner le SVG avec l' attribut heightet / ou widthsur la <svg>balise, au lieu de la propriété CSS background-size.
gitaarik
10
select  {
    outline: 0;
    overflow: hidden;
    height: 30px;
    background: #2c343c;
    color: #747a80;
    border: #2c343c;
    padding: 5px 3px 5px 10px;
    -moz-border-radius: 6px;
    -webkit-border-radius: 6px;
    border-radius: 10px;
}

select option {border: 1px solid #000; background: #010;}
gecko
la source
Impossible de sélectionner quoi que ce soit avec cela avec Chrome actuel.
Vitaly Zdanevich
9

Sélectionner des styles CSS personnalisés

Testé dans Internet Explorer (10 et 11), Edge, Firefox et Chrome

select::-ms-expand {
  display: none;
}
select {
  display: inline-block;
  box-sizing: border-box;
  padding: 0.5em 2em 0.5em 0.5em;
  border: 1px solid #eee;
  font: inherit;
  line-height: inherit;
  -webkit-appearance: none;
  -moz-appearance: none;
  -ms-appearance: none;
  appearance: none;
  background-repeat: no-repeat;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right 15px top 1em, right 10px top 1em;
  background-size: 5px 5px, 5px 5px;
}
<select name="">
  <option value="">Lorem</option>
  <option value="">Lorem Ipsum</option>
</select>

<select name="" disabled>
  <option value="">Disabled</option>
</select>

<select name="" style="color:red;">
  <option value="">Color!</option>
  <option value="">Lorem Ipsum</option>
</select>

Roko C. Buljan
la source
Légèrement plus adaptable (mais pas testé dans tous les navigateurs):background-position: right 15px center, right 10px center;
Robin Stewart
8

Utilisez la clippropriété pour rogner les bordures et la flèche de l' selectélément, puis ajoutez vos propres styles de remplacement au wrapper:

    <!DOCTYPE html>
    <html>
      <head>
        <style>
          select { position: absolute; clip:rect(2px 49px 19px 2px); z-index:2; }
          body > span { display:block; position: relative; width: 64px; height: 21px; border: 2px solid green;  background: url(http://www.stackoverflow.com/favicon.ico) right 1px no-repeat; }
        </style>
      </head>
      <span>
        <select>
          <option value="">Alpha</option>
          <option value="">Beta</option>
          <option value="">Charlie</option>
        </select>
      </span>
    </html>

Utilisez une seconde sélection avec une opacité nulle pour rendre le bouton cliquable:

    <!DOCTYPE html>
    <html>
      <head>
        <style>
          #real { position: absolute; clip:rect(2px 51px 19px 2px); z-index:2; }
          #fake { position: absolute; opacity: 0; }
    
          body > span { display:block; position: relative; width: 64px; height: 21px; background: url(http://www.stackoverflow.com/favicon.ico) right 1px no-repeat; }
        </style>
      </head>
      <span>
        <select id="real">
          <option value="">Alpha</option>
          <option value="">Beta</option>
          <option value="">Charlie</option>
        </select>
        <select id="fake">
          <option value="">Alpha</option>
          <option value="">Beta</option>
          <option value="">Charlie</option>
        </select>
      </span>
    </html>

Les coordonnées diffèrent entre Webkit et les autres navigateurs, mais une requête @media peut couvrir cela.

Références

Paul Sweatte
la source
1
Fonctionne bien pour moi, au moins en chrome: position: absolue; clip: rect (2px 85px 128px 2px); indice z: 2; rembourrage gauche: 18px; rembourrage à droite: 18px; marge: 7px auto; couleur: # 555; taille de police: hériter; couleur de fond: transparent;
BrianFreud
1
J'ai trouvé que le découpage de la flèche ne fonctionne qu'à moitié dans IE7 car vous n'avez aucun contrôle sur la bordure de la sélection.
CpILL
1
Ajout de la fonctionnalité de clic dans le cadre d'une question connexe
Paul Sweatte
1
@PaulSweatte, wow, c'est votre 20e nécromancien ! Félicitations. Vous avez également surmonté toutes mes requêtes pour un badge de nécromancien en or .
Nemo
5

Un très bel exemple qui utilise :afteret :beforepour faire l'astuce est dans Styling Select Box avec CSS3 | CSSDeck

Ahmad Ajmi
la source
1
Oui, mais l'exigence en question était compatible avec Internet Explorer 6,7 et 8
Jitendra Vyas
2
Oui, ce n'est pas compatible avec IE, mais j'ai adoré partager pour tous ceux qui recherchent une solution moderne comme je le cherchais.
Ahmad Ajmi
5

Modifier cet élément n'est pas recommandé, mais si vous voulez l'essayer, c'est comme n'importe quel autre élément HTML.

Modifier l'exemple:

/* Edit select */
select {
    /* CSS style here */
}

/* Edit option */
option {
    /* CSS style here */
}

/* Edit selected option */
/* element  attr    attr value */
option[selected="selected"] {
    /* CSS style here */
}
<select>
    <option >Something #1</option>
    <option selected="selected">Something #2</option>
    <option >Something #3</option>
</select>
Homar
la source
2
@MikkoP: lorsque vous proposez des modifications, pourriez-vous fournir un résumé des modifications plus descriptif? "Amélioration du message" n'est pas très utile en tant que résumé de haut niveau pour nous, évaluateurs. Merci.
Jean-François Corbett
1
@ Jean-FrançoisCorbett Je vais essayer d'être plus précis :)
MikkoP
1
vous ne pouvez pas
styliser les
4
label {
    position: relative;
    display: inline-block;
}
select {
    display: inline-block;
    padding: 4px 3px 5px 5px;
    width: 150px;
    outline: none;
    color: black;
    border: 1px solid #C8BFC4;
    border-radius: 4px;
    box-shadow: inset 1px 1px 2px #ddd8dc;
    background-color: lightblue;
}

Cela utilise une couleur d'arrière-plan pour certains éléments et j'ai supprimé l'image.

Chanceux
la source
4

Oui. Vous pouvez styliser n'importe quel élément HTML par son nom de balise, comme ceci:

select {
  font-weight: bold;
}

Bien sûr, vous pouvez également utiliser une classe CSS pour la styliser, comme tout autre élément:

<select class="important">
  <option>Important Option</option>
  <option>Another Important Option</option>
</select>

<style type="text/css">
  .important {
    font-weight: bold;
  }
</style>
Dave Ward
la source
6
je ne parle pas comme ça je veux changer la flèche du menu déroulant pour autre chose
Jitendra Vyas
5
Vous ne pouvez pas styliser la flèche déroulante sur une autre image, elle est contrôlée par le système d'exploitation. Si vous en avez vraiment besoin, le mieux est d'utiliser un widget déroulant DHTML.
Ryan Doherty
3
Vous ne pouvez modifier les propriétés CSS que via CSS. Vous pouvez modifier sa marge, son remplissage, ses propriétés de police, sa couleur d'arrière-plan, etc. ).
Dave Ward
4

Voici une solution basée sur mes idées préférées de cette discussion. Cela permet de styliser un élément <select> directement sans aucun balisage supplémentaire.

Il fonctionne avec Internet Explorer 10 (et versions ultérieures) avec une solution de secours sûre pour Internet Explorer 8/9. Une mise en garde pour ces navigateurs est que l'image d'arrière-plan doit être positionnée et suffisamment petite pour se cacher derrière le contrôle d'extension natif.

HTML

<select name='options'>
  <option value='option-1'>Option 1</option>
  <option value='option-2'>Option 2</option>
  <option value='option-3'>Option 3</option>
</select>

SCSS

body {
  padding: 4em 40%;
  text-align: center;
}

select {
  $bg-color: lightcyan;
  $text-color: black;
  appearance: none; // Using -prefix-free http://leaverou.github.io/prefixfree/
  background: {
    color: $bg-color;
    image: url("https://s3-us-west-2.amazonaws.com/s.cdpn.io/1255/caret--down-15.png");
    position: right;
    repeat: no-repeat;
  }
  border: {
    color: mix($bg-color, black, 80%);
    radius: .2em;
    style: solid;
    width: 1px;
    right-color: mix($bg-color, black, 60%);
    bottom-color: mix($bg-color, black, 60%);
  }
  color: $text-color;
  padding: .33em .5em;
  width: 100%;
}

// Removes default arrow for Internet Explorer 10 (and later)
// Internet Explorer 8/9 gets the default arrow which covers the caret
// image as long as the caret image is smaller than and positioned
// behind the default arrow
select::-ms-expand {
    display: none;
}

CodePen

http://codepen.io/ralgh/pen/gpgbGx

ralgh
la source
3

Il existe un moyen simple.

Vérifiez ce violon, et pardonnez-moi le sur-style: https://jsfiddle.net/dkellner/7ac9us70/

L'astuce derrière: dès que la balise <select> obtient une propriété appelée "taille", elle se comportera comme une liste à hauteur fixe, et, tout à coup, pour une raison quelconque, vous permet de créer un style d'enfer. À proprement parler, la liste fixe est un effet secondaire - mais elle nous aide simplement davantage car nous l'utilisons pour le "look déroulant".

Un exemple minimal:

<style>

    .stylish span   {position:relative;}
    .stylish select {position:absolute;left:0px;display:none}

</style>
...
<div class="stylish">
    <label> Choose your superhero: </label>
    <span>
        <input onclick="$(this).closest('div').find('select').slideToggle(110)"><br>
        <select size=15 onclick="$(this).hide().closest('div').find('input').val($(this).find('option:selected').text());">

            <optgroup label="Fantasy"></optgroup>
            <option value="1">  Gandalf        </option>
            <option value="2">  Harry Potter   </option>
            <option value="3">  Jon Snow       </option>

            <!-- ... and so on -->

        </select>
    </span>
</div>

(pour faire simple, je l'ai fait avec jQuery - mais vous pouvez faire la même chose sans)

Notes annexes

  • Cette solution vous offre plus qu'un simple choix: la valeur est également modifiable manuellement. Utilisez la propriété en lecture seule si vous préférez la méthode restreinte par sélection par défaut.

  • Pour maximiser les possibilités de style, les balises <optgroup> ne sont pas autour de leurs enfants, elles sont déplacées devant eux. C'est intentionnel, c'est plus clair visuellement, et ils sont heureux de travailler comme ça, ne vous inquiétez pas.

  • Javascripts: oui je sais que l'OP a dit "pas de Javascript" mais je l'ai compris car s'il vous plaît ne vous embêtez pas avec les plugins , ce qui est bien. Vous n'avez besoin d'aucune bibliothèque pour celle-ci. Pas même jQuery, comme je l'ai dit, c'est uniquement pour la clarté de l'exemple.

dkellner
la source
2

Vous devriez certainement le faire comme dans Styling select, optgroup et options avec CSS . À bien des égards, la couleur d'arrière-plan et la couleur sont exactement ce dont vous auriez généralement besoin pour styliser les options, pas la sélection entière.

Otvazhnii
la source
2

Vous pouvez également ajouter un style de survol à la liste déroulante.

select {position:relative; float:left; width:21.4%; height:34px; background:#f9f9e0; border:1px solid #41533f; padding:0px 10px 0px 10px; color:#41533f; margin:-10px 0px 0px 20px; background: transparent; font-size: 12px; -webkit-appearance: none; -moz-appearance: none; appearance: none; background: url(https://alt-fit.com/images/global/select-button.png) 100% / 15% no-repeat #f9f9e0;}
select:hover {background: url(https://alt-fit.com/images/global/select-button.png) 100% / 15% no-repeat #fff;}
<html>
<head>
</head>
<body>
<select name="type" class="select"><option style="color:#41533f;" value="Select option">Select option</option>
<option value="Option 1">Option 1</option>
<option value="Option 2">Option 2</option>
<option value="Option 3">Option 3</option>
</select>
</body>
</html>


la source
2

La troisième méthode dans la réponse de Danield peut être améliorée pour fonctionner avec les effets de et d'autres événements de souris. Assurez-vous simplement que l'élément "bouton" vient juste après l'élément de sélection dans le balisage. Puis ciblez-le en utilisant le sélecteur + CSS:

HTML:

<select class="select-input">...</select>
<div class="select-button"></div>

CSS:

.select-input:hover+.select-button {
    <Hover styles here>
}

Cela montrera cependant l'effet de survol lorsque vous survolerez n'importe où sur l'élément de sélection, pas seulement sur le "bouton".

J'utilise cette méthode en combinaison avec Angular (puisque mon projet se trouve être une application Angular de toute façon), pour couvrir tout l'élément de sélection, et laisser Angular afficher le texte de l'option sélectionnée dans l'élément "bouton". Dans ce cas, il est parfaitement logique que l'effet de survol s'applique lorsque vous survolez n'importe où sur la sélection.

Cependant, cela ne fonctionne pas sans JavaScript, donc si vous voulez le faire, et votre site doit fonctionner sans JavaScript, vous devez vous assurer que votre script ajoute les éléments et les classes nécessaires à l'amélioration. De cette façon, un navigateur sans JavaScript obtiendra simplement une sélection normale, sans style, au lieu d'un badge de style qui ne se met pas à jour correctement.

Adrian Schmidt
la source
1
J'adorerais connaître la raison de tout downvote, donc je peux savoir comment m'améliorer! 🙂
Adrian Schmidt
1

Une solution CSS et HTML uniquement

Il semble compatible avec Chrome, Firefox et Internet Explorer 11. Mais veuillez laisser vos commentaires concernant les autres navigateurs Web.

Comme suggéré par la réponse de Danield, j'emballe ma sélection dans un div (même deux div pour la compatibilité avec x-browser) pour obtenir le comportement attendu.

Voir http://jsfiddle.net/bjap2/

HTML:

<div class="sort-options-wrapper">
    <div class="sort-options-wrapper-2">
        <select class="sort-options">
                <option value="choiceOne">choiceOne</option>
                <option value="choiceOne">choiceThree</option>
                <option value="choiceOne">choiceFour</option>
                <option value="choiceFiveLongTestPurpose">choiceFiveLongTestPurpose</option>
        </select>
    </div>
    <div class="search-select-arrow-down"></div>
</div>

Remarquez les deux enveloppes div.

Notez également le div supplémentaire ajouté pour placer le bouton fléché vers le bas où vous le souhaitez (positionné absolument), nous le mettons ici à gauche.

CSS

.sort-options-wrapper {
    display: inline-block;
    position: relative;
    border: 1px solid #83837F;
}

/* This second wrapper is needed for x-browser compatibility */
.sort-options-wrapper-2 {
    overflow: hidden;
}

select {
    margin-right: -19px; /* That's what is hiding the default-provided browser arrow */
    padding-left: 13px;
    margin-left: 0;
    border: none;
    background: none;

    /* margin-top & margin-bottom must be set since some
       browsers have default values for select elements */
    margin-bottom: 1px;
    margin-top: 1px;
}

select:focus {
    outline: none; /* Removing default browsers outline on focus */
}
.search-select-arrow-down {
    position: absolute;
    height: 10px;
    width: 12px;
    background: url(http://i.imgur.com/pHIYN06.png) scroll no-repeat 2px 0px;
    left: 1px;
    top: 5px;
}
Adrien Be
la source