Come modifico un menu a discesa <select> con solo CSS?


1333

Esiste un modo solo CSS di <select>definire un menu a discesa?

Ho bisogno di modellare un <select>modulo il più umanamente possibile, senza JavaScript. Quali sono le proprietà che posso usare per farlo nei CSS?

Questo codice deve essere compatibile con tutti i principali browser:

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

So di poterlo fare con JavaScript: esempio .

E non sto parlando di stile semplice. Voglio sapere qual è il meglio che possiamo fare solo con i CSS.

Ho trovato domande simili su Stack Overflow.

E questo su Doctype.com.


1
non c'è molto da trovare su Google, l'unica soluzione js è lì
Jitendra Vyas,

41
Sento che è una domanda legittima, ma la risposta è "no, non proprio" o "non nel modo desiderato". Ma nessuno (né io) ne è sicuro al 100%, questa sensazione di ambiguità striscia sotto la pelle del lettore e la legittimità della domanda viene messa in discussione.
ZJR,

1
@Jitendra, so a cosa stai arrivando. Ci piacerebbe se rendessi la tua domanda più esplicita. Inoltre, penso di aver trovato quello che potresti cercare. Questo è sperimentale, ma dai un'occhiata: cappuccino.org/aristo/showcase
jeremyosborne,

1
@jeremyosborne - Grazie per la risposta. So che posso farcela con JavaScript. il tuo link eaxmple si basa su JS. Perché ho posto questa domanda perché volevo sapere, c'è qualcuno che sa cosa possiamo fare meglio solo con i CSS
Jitendra Vyas,

@Jitendra Grazie per aver aggiornato la tua domanda. Il meglio che puoi fare in modo affidabile con i vincoli che hai (solo CSS e no JS) è modificare il carattere tipografico (font), i colori di sfondo e di primo piano (testo), le dimensioni del bordo, l'aspetto e i colori, il posizionamento e le dimensioni (di solito tramite il tipo impostazione tramite font). Anche allora, probabilmente dovrai fare alcune modifiche per assicurarti che le cose siano uguali su tutti i browser. Vorrei sapere una risposta migliore di quella, e forse ce n'è una che mi è sfuggita, ma non credo.
Jeremyosborne,

Risposte:


1028

Ecco tre soluzioni:

Soluzione n. 1 - aspetto: nessuno - con soluzione alternativa a Internet Explorer 10-11 ( Demo )

-

Per nascondere la freccia predefinita impostata appearance: nonesull'elemento select, quindi aggiungi la tua freccia personalizzata conbackground-image

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

Supporto browser:

appearance: noneha un ottimo supporto per il browser ( caniuse ) - ad eccezione di Internet Explorer 11 (e versioni successive) e Firefox 34 (e versioni successive).

Possiamo migliorare questa tecnica e aggiungere il supporto per Internet Explorer 10 e Internet Explorer 11 aggiungendo

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

Se Internet Explorer 9 è un problema, non abbiamo modo di rimuovere la freccia predefinita (il che significherebbe che ora avremmo due frecce), ma potremmo usare un selettore funky di Internet Explorer 9.

Per annullare almeno la nostra freccia personalizzata, lasciando intatta la freccia di selezione predefinita.

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

Tutti insieme:

Questa soluzione è semplice e ha un buon supporto per il browser - dovrebbe generalmente essere sufficiente.


Se è necessario il supporto del browser per Internet Explorer 9 (e versioni successive) e Firefox 34 (e versioni successive), continua a leggere ...

Soluzione n. 2 Tronca l'elemento select per nascondere la freccia predefinita ( demo )

-

(Leggi di più qui)

Avvolgi l' selectelemento in un div con una larghezza fissa e overflow:hidden.

Quindi assegna selectall'elemento una larghezza di circa 20 pixel maggiore del div .

Il risultato è che la freccia a discesa predefinita selectdell'elemento sarà nascosta (a causa della presenza overflow:hiddensul contenitore) e puoi posizionare qualsiasi immagine di sfondo che desideri sul lato destro del div.

Il vantaggio di questo approccio è che è cross-browser (Internet Explorer 8 e versioni successive, WebKit e Gecko ). Tuttavia, lo svantaggio di questo approccio è che il menu a discesa delle opzioni si sporge sul lato destro (dai 20 pixel che abbiamo nascosto ... perché gli elementi delle opzioni assumono la larghezza dell'elemento selezionato).

Inserisci qui la descrizione dell'immagine

[Va notato, tuttavia, che se l'elemento di selezione personalizzato è necessario solo per i dispositivi mobili - quindi il problema sopra riportato non si applica - a causa del modo in cui ciascun telefono apre nativamente l'elemento di selezione. Quindi, per i dispositivi mobili, questa potrebbe essere la soluzione migliore.]


Se la freccia personalizzata è necessaria su Firefox, prima della versione 35 , ma non è necessario supportare le versioni precedenti di Internet Explorer, continua a leggere ...

Soluzione n. 3: utilizzare la pointer-eventsproprietà ( demo )

-

(Leggi di più qui)

L'idea qui è di sovrapporre un elemento sopra la freccia a discesa nativa (per crearne uno personalizzato) e quindi non consentire eventi puntatore su di esso.

Vantaggio: funziona bene in WebKit e Gecko. Sembra anche buono (nessun optionelemento sporgente ).

Svantaggio: Internet Explorer (Internet Explorer 10 e versioni precedenti) non supporta pointer-events, il che significa che non è possibile fare clic sulla freccia personalizzata. Inoltre, un altro (ovvio) svantaggio di questo metodo è che non puoi scegliere come target la tua nuova freccia con un effetto hover o cursore della mano, perché abbiamo appena disabilitato gli eventi del puntatore su di essi!

Tuttavia, con questo metodo è possibile utilizzare Modernizer o commenti condizionali per ripristinare la freccia incorporata standard in Internet Explorer.

NB: Essendo che Internet Explorer 10 non supporta conditional commentspiù: se vuoi usare questo approccio, dovresti probabilmente usare Modernizr . Tuttavia, è ancora possibile escludere i CSS degli eventi puntatore da Internet Explorer 10 con un hack CSS descritto qui .


1
Qual è il migliore secondo te da questi 2 metodi?
Jitendra Vyas,

3
Dipende dai requisiti di progettazione. Se stai bene con il menu a discesa che si sporge, allora è il migliore perché è cross-browser (tutti i browser IMO + IE8 + potrebbero essere considerati cross-browser) ma penso a molti - questo non lo farà. Quindi, in realtà, nella mia affermazione sopra, intendevo dire che l'approccio n. 2 era il migliore.
Danield,

4
Inoltre, il violino che ho pubblicato utilizza l'approccio n. 2 con istruzioni condizionali per consentire a IE di utilizzare la sua freccia predefinita.
Danield,

3
@AlexisLeclerc Risolvere il div e selezionare la stessa larghezza funziona solo nei browser -webkit come Chrome. (perché ho incluso la regola - webkit-aspetto: nessuno; ) Tuttavia, questo non funziona in altri browser come Firefox
Danield,

4
Se posso proporre un miglioramento per l'approccio n. 1, trovo personalmente la mancanza di confine o la mancanza di un alone di selezione sul lato destro molto fastidioso. Ho aggiornato il tuo violino con qualcosa che ho usato nel mio progetto attuale: jsfiddle.net/YvCHW/1745 . Ditemi cosa ne pensate!
Alexis Leclerc,

233

È possibile, ma sfortunatamente per lo più nei browser basati su WebKit nella misura in cui, come sviluppatori, richiediamo. Ecco l'esempio dello stile CSS raccolto dal pannello delle opzioni di Chrome tramite la finestra di ispezione degli strumenti di sviluppo integrata, migliorata per abbinare le proprietà CSS attualmente supportate nella maggior parte dei browser moderni:

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;
}

Quando esegui questo codice su qualsiasi pagina all'interno di un browser basato su WebKit, dovrebbe cambiare l'aspetto della casella di selezione, rimuovere la freccia del sistema operativo standard e aggiungere una freccia PNG, mettere un po 'di spazio prima e dopo l'etichetta, quasi tutto ciò che desideri.

La parte più importante è la appearanceproprietà, che cambia il comportamento dell'elemento.

Funziona perfettamente in quasi tutti i browser basati su WebKit, compresi quelli mobili, anche se Gecko non supporta appearancecosì come WebKit, a quanto pare.


4
Ehi, ho notato che le caselle di selezione hanno iniziato a sembrare molto diverse da Firefox 12 (sembra MOLTO simile a Chrome (ho un Mac)) e sembra che FF 12 supporti un sacco di attributi di aspetto.
CWSpear

3
una soluzione solo per Chrome ... Non pagherei per questo, né per il mio cliente. vedi la risposta di @Dianeld per una soluzione x-browser.
Adrien,

41
@AdrienBe La mia soluzione è stata proposta quasi 3 anni fa; al momento era l'unico modo ragionevole per ridisegnare le caselle selezionate senza coinvolgere librerie o plugin JavaScript. È ancora fattibile se decidi di eliminare gli attributi prefissati, ma funziona in modo affidabile solo nei browser basati su Webkit (quindi Safari, anche Opera + Android). In questo momento, ci sono forse soluzioni migliori, quindi invece di aggiungere commenti insignificanti, vota solo per la soluzione che ritieni migliore e in futuro controlla la data di "risposta". Grazie.
Matthew Morek,

4
@MatthewMorek: c'era una soluzione migliore, anche 3 anni fa. La risposta di Daniel è molto migliore per quanto riguarda il supporto cross-browser (supporta IE8 e versioni successive, WebKit e Gecko). La domanda è stata posta "il codice deve essere compatibile con tutti i principali browser: Internet Explorer 6,7 e 8, Firefox e Safari". Questo requisito per x-browser potrebbe essere stato aggiunto da Paul Sweatte nel 2013 ... scusate se è il caso.
Adrien, l'

3
Se lo aggiungi text-indent: 0.01px; text-overflow: "";funzionerà ancora meglio
Ivan,

64

L'elemento select e la sua funzione di menu a discesa sono difficili da definire.

gli attributi di stile per l'elemento selezionato di Chris Heilmann confermano ciò che Ryan Dohery ha detto in un commento alla prima risposta:

"L'elemento select fa parte del sistema operativo, non il browser Chrome. Pertanto, è molto inaffidabile per lo stile e non ha necessariamente senso provare comunque."


47

Ho avuto questo esatto problema, tranne per il fatto che non potevo usare le immagini e non ero limitato dal supporto del browser. Questo dovrebbe essere «su specifica» e con un po 'di fortuna iniziare a lavorare ovunque alla fine .

Utilizza livelli di sfondo ruotati a strati per «ritagliare» una freccia a discesa, poiché gli pseudo-elementi non funzionerebbero per l'elemento selezionato.

Modifica: in questa versione aggiornata sto usando variabili CSS e un piccolo sistema di temi.

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


5
Caspita, questa è una delle soluzioni più interessanti che abbia mai visto. Funziona per me nelle ultime versioni di Chrome e Safari su Mac. Che ne dici di altri browser?
Tintin81,

2
Funziona per me in Firefox con l'aggiunta di-moz-appearance: none;
Zac

45

La più grande incoerenza che ho notato quando si selezionano i menu a discesa di selezione è il rendering Safari e Google Chrome (Firefox è completamente personalizzabile tramite CSS). Dopo alcune ricerche in oscure profondità di Internet mi sono imbattuto in quanto segue, che risolve quasi completamente i miei dubbi con WebKit:

Safari e correzione di Google Chrome :

select {
  -webkit-appearance: none;
}

Questo, tuttavia, rimuove la freccia del menu a discesa. È possibile aggiungere una freccia a discesa utilizzando una freccia vicina divcon uno sfondo, un margine negativo o posizionata in modo assoluto sopra il menu a discesa selezionato.

* Ulteriori informazioni e altre variabili sono disponibili nella proprietà CSS: -webkit-aspect .


1
Non dimenticare di aggiungere il tuo stile dopo quello;) Ma sono molto felice di aver letto questo commento oggi.
teewuane,

1
potresti per favore approfondire la tua affermazione: "Firefox è completamente personalizzabile tramite CSS" per me sembra che Firefox non supporti la proprietà di apparenza ... quindi come si farebbe in Firefox?
Danield,

36

<select>i tag possono essere modellati tramite CSS proprio come qualsiasi altro elemento HTML su una pagina HTML renderizzata in un browser. Di seguito è riportato un esempio (eccessivamente semplice) che posizionerà un elemento selezionato sulla pagina e renderà il testo delle opzioni in blu.

Esempio di file 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>

Esempio di file 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;
}

30
Incredibile, la prima volta che ho visto "madri" coinvolte su Internet senza essere scortese. +1 per quello!
BaL

34
Questa risposta non risolve questa domanda. Solo gli stili selezionano l'input ma non il menu a discesa
Kyborek,

14
Questa risposta ignora totalmente le sfide poste dalla definizione di un elenco a discesa per la coerenza tra browser. Questa è una risposta di sforzo molto basso.
BentOnCoding

18

Il post del blog How to CSS form drop down style no JavaScript funziona per me, ma non funziona in Opera però:

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>


17

Ecco una versione che funziona in tutti i browser moderni. La chiave sta usandoappearance:none che rimuove la formattazione predefinita. Poiché tutta la formattazione è sparita, è necessario aggiungere nuovamente la freccia che differenzia visivamente la selezione dall'input.

Esempio di lavoro: 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>


16

Sono arrivato al tuo caso usando Bootstrap . Questa è la soluzione più semplice che funziona:

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>

Nota: l'elemento base64 è fa-chevron-downin formato SVG.


12

Nei browser moderni è relativamente indolore dare uno stile al <select>CSS. Con appearance: nonel'unica parte difficile è sostituire la freccia (se è quello che vuoi). Ecco una soluzione che utilizza un data:URI inline con SVG in testo semplice:

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>

Il resto dello stile (bordi, imbottitura, colori, ecc.) È abbastanza semplice.

Funziona con tutti i browser che ho appena provato (Firefox 50, Chrome 55, Edge 38 e Safari 10). Una nota su Firefox è che se si desidera utilizzare il #carattere nell'URI dei dati (ad es. fill: #000) È necessario evitarlo ( fill: %23000).


1
Puoi anche ridimensionare l'SVG con l' attributo heighte / o widthsul <svg>tag, anziché la proprietà 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;}

Non è possibile selezionare nulla con quello con Chrome corrente.
Vitaly Zdanevich,

9

Personalizzato Seleziona gli stili CSS

Testato in Internet Explorer (10 e 11), Edge, Firefox e 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>


Leggermente più adattabile (ma non testato in tutti i browser):background-position: right 15px center, right 10px center;
Robin Stewart

8

Usa la clipproprietà per ritagliare i bordi e la freccia selectdell'elemento, quindi aggiungi i tuoi stili di sostituzione al 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>

Utilizzare una seconda selezione con zero opacità per rendere selezionabile il pulsante:

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

Le coordinate differiscono tra Webkit e altri browser, ma una query @media può coprirlo.

Riferimenti


1
Funziona bene per me, almeno in Chrome: posizione: assoluto; clip: rect (2px 85px 128px 2px); indice z: 2; imbottitura-sinistra: 18px; imbottitura-destra: 18px; margine: 7px auto; colore: # 555; dimensione carattere: ereditare; colore di sfondo: trasparente;
BrianFreud,

1
Ho scoperto che ritagliare la freccia funziona solo per metà in IE7 poiché non hai alcun controllo sul bordo della selezione.
CpILL,

1
Aggiunta la funzionalità clic come parte di una domanda correlata
Paul Sweatte,

1
@PaulSweatte, wow, questo è il tuo 20esimo negromante ! Congratulazioni. Hai anche superato tutte le mie domande per un badge da negromante d'oro .
Nemo,


5

Modifica questo elemento non è raccomandato, ma se vuoi provarlo è come qualsiasi altro elemento HTML.

Modifica esempio:

/* 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>

2
@MikkoP: quando suggerisci le modifiche, potresti fornire un riepilogo delle modifiche più descrittivo? "Migliorato il messaggio" non è molto utile come riepilogo di alto livello per noi revisori. Grazie.
Jean-François Corbett,

1
@ Jean-FrançoisCorbett Proverò ad essere più specifico :)
MikkoP,

1
non si può elementi di opzione di stile (vedi questo SO risposta: stackoverflow.com/a/7208814/703717 )
DanielD

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;
}

Questo utilizza un colore di sfondo per selezionare gli elementi e ho rimosso l'immagine ..


4

Sì. Puoi assegnare uno stile a qualsiasi elemento HTML in base al nome del tag, in questo modo:

select {
  font-weight: bold;
}

Naturalmente, puoi anche usare una classe CSS per modellarla, come qualsiasi altro elemento:

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

<style type="text/css">
  .important {
    font-weight: bold;
  }
</style>

6
non sto parlando in questo modo, voglio cambiare la freccia del menu a discesa in qualcos'altro
Jitendra Vyas,

5
Non è possibile assegnare la freccia del menu a discesa a un'altra immagine, è controllata dal sistema operativo. Se è davvero necessario, la soluzione migliore è utilizzare un widget a discesa DHTML.
Ryan Doherty,

3
Puoi modificare le proprietà CSS solo tramite CSS. Puoi cambiarne il margine, il riempimento, le proprietà del carattere, il colore di sfondo, ecc. Se vuoi renderlo completamente diverso, devi sostanzialmente sostituirlo con la grafica in fase di esecuzione tramite JavaScript (che non è una soluzione terribile se fatto bene ).
Dave Ward

4

Ecco una soluzione basata sulle mie idee preferite da questa discussione. Ciò consente di definire direttamente un elemento <select> senza alcun markup aggiuntivo.

Funziona con Internet Explorer 10 (e versioni successive) con un fallback sicuro per Internet Explorer 8/9. Un avvertimento per questi browser è che l'immagine di sfondo deve essere posizionata ed essere abbastanza piccola da nascondersi dietro il controllo di espansione nativo.

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



3

C'è un modo semplice.

Dai un'occhiata a questo violino e perdonami lo stravagante: https://jsfiddle.net/dkellner/7ac9us70/

Il trucco dietro: non appena il tag <select> ottiene una proprietà chiamata "size", si comporterà come un elenco ad altezza fissa e, all'improvviso, per qualche motivo, ti permetterà di dargli uno stile. Ora, a rigor di termini, l'elenco fisso è un effetto collaterale, ma ci aiuta solo di più perché lo utilizziamo per "l'aspetto a discesa".

Un esempio minimo:

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

(per semplificare, l'ho fatto con jQuery - ma puoi fare lo stesso senza di esso)

Note a margine

  • Questa soluzione ti offre molto più di una selezione: il valore è anche modificabile manualmente. Utilizzare la proprietà readonly se si preferisce il modo limitato con selezione predefinita.

  • Per massimizzare le possibilità di stile, i tag <optgroup> non sono intorno ai loro figli, ma sono stati spostati prima loro. È intenzionale, è visivamente più chiaro e sono felici di lavorare in questo modo, non ti preoccupare.

  • Javascripts: sì, so che l'OP ha detto "no Javascript", ma l'ho capito, per favore, non preoccuparti dei plugin , il che va bene. Non hai bisogno di alcuna libreria per questo. Nemmeno jQuery, come ho detto, è solo per la chiarezza dell'esempio.



2

Puoi anche aggiungere uno stile hover al menu a discesa.

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>


2

Il terzo metodo nella risposta di Danield può essere migliorato per funzionare con effetti hover e altri eventi del mouse. Assicurati solo che l'elemento "pulsante" arrivi subito dopo l'elemento select nel markup. Quindi scegli come target utilizzando il selettore + CSS:

HTML:

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

CSS:

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

Questo, tuttavia, mostrerà l'effetto hover quando passi con il mouse sopra l'elemento select, non solo sul "pulsante".

Sto usando questo metodo in combinazione con Angular (dato che il mio progetto sembra essere comunque un'applicazione Angular), per coprire l'intero elemento selezionato e lasciare che Angular visualizzi il testo dell'opzione selezionata nell'elemento "pulsante". In questo caso ha perfettamente senso che l'effetto hover si applichi quando si passa con il mouse sopra la selezione.

Tuttavia, non funziona senza JavaScript, quindi se vuoi farlo e il tuo sito deve funzionare senza JavaScript, dovresti assicurarti che il tuo script aggiunga gli elementi e le classi necessarie per il miglioramento. In questo modo, un browser senza JavaScript otterrà semplicemente un normale, non stilato, selezionare, invece di un badge in stile che non si aggiorna correttamente.


1
Mi piacerebbe sapere il motivo di eventuali downgrade, così posso sapere come migliorare! 🙂
Adrian Schmidt,

1

Una soluzione solo CSS e HTML

Sembra compatibile con Chrome, Firefox e Internet Explorer 11. Ma ti preghiamo di lasciare il tuo feedback in merito ad altri browser web.

Come suggerito dalla risposta di Danield , avvolgo la mia selezione in un div (anche due div per la compatibilità con x-browser) per ottenere il comportamento previsto.

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

Notare i due wrapper div.

Nota anche il div extra aggiunto per posizionare il pulsante freccia giù dove vuoi (posizionato assolutamente), qui lo posizioniamo a sinistra.

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;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.