Como faço para estilizar um menu suspenso <selecionar> apenas com CSS?

1333

Existe uma maneira apenas de CSS de estilizar um <select>menu suspenso?

Preciso estilizar um <select>formulário da forma mais humanamente possível, sem nenhum JavaScript. Quais são as propriedades que posso usar para fazer isso em CSS?

Esse código precisa ser compatível com todos os principais navegadores:

  • Internet Explorer 6, 7 e 8
  • Raposa de fogo
  • Safári

Eu sei que posso fazê-lo com JavaScript: exemplo .

E não estou falando de estilo simples. Quero saber o melhor que podemos fazer apenas com CSS.

Encontrei perguntas semelhantes no Stack Overflow.

E esse aqui no Doctype.com.

Jitendra Vyas
fonte
1
nada muito encontrada no google única solução js está lá
Jitendra Vyas
41
Eu sinto que é uma pergunta legítima, mas a resposta é "não, não realmente" ou "não do jeito que você quer". Mas ninguém (nem eu) tem 100% de certeza disso, esse sentimento de ambiguidade se arrasta por baixo da pele do leitor e a legitimidade da pergunta é questionada.
ZJR
1
@Jitendra, eu sei o que você está fazendo. Adoraríamos que você tornasse sua pergunta mais explícita. Além disso, acho que encontrei o que você poderia estar procurando. Esta é experimental, mas confira: cappuccino.org/aristo/showcase
jeremyosborne
1
@jeremyosborne - Obrigado pela resposta. Eu sei que posso fazê-lo com javascript. seu link eaxmple é baseado em JS. Por que eu fiz esta pergunta porque eu queria saber, é de ninguém lá sabe sobre o melhor que podemos fazer com apenas css
Jitendra Vyas
@Jitendra Obrigado por atualizar sua pergunta. O melhor que você pode fazer com segurança com as restrições que você possui (apenas CSS e sem JS) é modificar as cores do tipo de letra (fonte), plano de fundo e primeiro plano (texto), tamanho da borda, aparência e cores, posicionamento e tamanho (geralmente por meio do tipo configuração através da fonte). Mesmo assim, você provavelmente precisará fazer alguns ajustes para garantir que as coisas tenham a mesma aparência em todos os navegadores. Eu gostaria de ter uma resposta melhor do que essa, e talvez haja uma que eu tenha perdido, mas acho que não.
jeremyosborne

Respostas:

1028

Aqui estão três soluções:

Solução # 1 - aparência: nenhuma - com solução alternativa para o Internet Explorer 10 - 11 ( demonstração )

-

Para ocultar a seta padrão definida appearance: noneno elemento de seleção, adicione sua própria seta personalizada combackground-image

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

Suporte do navegador:

appearance: nonetem um suporte muito bom ao navegador ( caniuse ) - exceto o Internet Explorer 11 (e posterior) e Firefox 34 (e posterior).

Podemos melhorar essa técnica e adicionar suporte ao Internet Explorer 10 e Internet Explorer 11 adicionando

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

Se o Internet Explorer 9 for uma preocupação, não temos como remover a seta padrão (o que significaria que agora teríamos duas setas), mas poderíamos usar um seletor do Internet Explorer 9.

Para desfazer pelo menos nossa seta personalizada - deixando a seta de seleção padrão intacta.

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

Todos juntos:

Essa solução é fácil e possui um bom suporte ao navegador - geralmente deve ser suficiente.


Se o suporte ao navegador do Internet Explorer 9 (e posterior) e Firefox 34 (e posterior) for necessário, continue lendo ...

Solução # 2 Trunque o elemento de seleção para ocultar a seta padrão ( demo )

-

(Leia mais aqui)

Enrole o selectelemento em uma div com uma largura fixa e overflow:hidden.

Em seguida, dê ao selectelemento uma largura de cerca de 20 pixels maior que a div .

O resultado é que a seta suspensa padrão do selectelemento ficará oculta (devido ao overflow:hiddencontêiner) e você pode colocar qualquer imagem de plano de fundo desejada no lado direito da div.

A vantagem dessa abordagem é que ela é entre navegadores (Internet Explorer 8 e posterior, WebKit e Gecko ). No entanto, a desvantagem dessa abordagem é que o menu suspenso de opções se projeta no lado direito (pelos 20 pixels que ocultamos ... porque os elementos de opção assumem a largura do elemento de seleção).

Digite a descrição da imagem aqui

[No entanto, deve ser observado que, se o elemento de seleção personalizado for necessário apenas para dispositivos móveis - o problema acima não se aplica - devido à maneira como cada telefone abre nativamente o elemento de seleção. Portanto, para dispositivos móveis, essa pode ser a melhor solução.]


Se a seta personalizada for necessária no Firefox - anterior à versão 35 - mas você não precisar oferecer suporte a versões antigas do Internet Explorer - continue lendo ...

Solução # 3 - Use a pointer-eventspropriedade ( demo )

-

(Leia mais aqui)

A idéia aqui é sobrepor um elemento sobre a seta suspensa nativa (para criar uma personalizada) e, em seguida, não permitir eventos de ponteiro nele.

Vantagem: Funciona bem no WebKit e Gecko. Parece bom também (sem optionelementos salientes ).

Desvantagem: o Internet Explorer (Internet Explorer 10 e inferior) não suporta pointer-events, o que significa que você não pode clicar na seta personalizada. Além disso, outra desvantagem (óbvia) desse método é que você não pode segmentar sua nova imagem de seta com um efeito de foco ou cursor de mão, porque acabamos de desativar os eventos de ponteiro neles!

No entanto, com esse método, você pode usar o Modernizer ou comentários condicionais para fazer o Internet Explorer reverter para a seta incorporada padrão.

NB: Como o Internet Explorer 10 não suporta conditional commentsmais: se você deseja usar essa abordagem, provavelmente deve usar o Modernizr . No entanto, ainda é possível excluir o CSS de eventos do ponteiro do Internet Explorer 10 com um hack de CSS descrito aqui .

Danield
fonte
1
Qual é o melhor de acordo com você a partir desses 2 métodos?
Jitendra Vyas
3
Depende dos requisitos de design. Se você estiver de acordo com a lista suspensa, então é melhor porque é entre navegadores (todos os navegadores da IMO + IE8 + podem ser considerados entre navegadores), mas acho que para muitos - isso não serve. Na verdade, na minha afirmação acima, eu quis dizer que a aproximação nº 2 era a melhor.
10132 Danield
4
Além disso, o violino que publiquei usa a abordagem nº 2 com instruções condicionais para permitir que o IE use sua seta padrão.
DanielD
3
@AlexisLeclerc A correção da div e a seleção para a mesma largura só funciona em navegadores -webkit como o Chrome. (porque eu incluiu a regra - webkit-appearance: none; ) No entanto isso não funcionar em outros navegadores como o Firefox
DanielD
4
Se eu posso propor uma melhoria para a Abordagem 1, pessoalmente, considero irritante a falta de borda ou a falta de seleção para o lado direito. Atualizei seu violino com algo que usei no meu projeto atual: jsfiddle.net/YvCHW/1745 . Me diga o que você acha!
Alexis Leclerc
233

É possível, mas infelizmente principalmente nos navegadores baseados no WebKit, na medida em que, como desenvolvedores, exigimos. Aqui está o exemplo de estilo CSS reunido no painel de opções do Chrome por meio do inspetor de ferramentas de desenvolvedor integrado, aprimorado para corresponder às propriedades CSS atualmente suportadas nos navegadores mais modernos:

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 você executa esse código em qualquer página de um navegador baseado no WebKit, ele deve alterar a aparência da caixa de seleção, remover a seta padrão do SO e adicionar uma seta PNG, colocar algum espaçamento antes e depois do rótulo, quase o que você desejar.

A parte mais importante é a appearancepropriedade, que altera a forma como o elemento se comporta.

Funciona perfeitamente em quase todos os navegadores baseados no WebKit, incluindo os móveis, embora o Gecko não suporte appearancetão bem quanto o WebKit, ao que parece.

Matthew Morek
fonte
4
Ei, eu notei que as caixas de seleção começaram a parecer muito diferentes no Firefox 12 (parece muito com o Chrome (eu tenho um Mac)), e parece que o FF 12 suporta muitos outros atributos de aparência.
CWpearear
3
uma solução apenas para cromo ... Eu não pagaria por isso, nem meu cliente. veja a resposta de @ Dianeld para uma solução de navegador x.
Adrien Seja
41
@AdrienBe Minha solução foi proposta há quase 3 anos; na época, era a única maneira razoável de mudar o estilo das caixas de seleção sem envolver libs ou plug-ins de JavaScript. Ainda é viável se você optar por descartar os atributos prefixados, mas ele funciona de maneira confiável apenas em navegadores baseados no Webkit (como o Safari, o novo Opera + Android também). No momento, talvez haja soluções melhores; portanto, em vez de adicionar comentários sem sentido, basta votar na solução que você vê como melhor e, no futuro, verificar a data "respondida". Obrigado.
Matthew Morek
4
@ MatthewMorek: havia uma solução melhor, mesmo 3 anos atrás. A resposta de Daniel é muito melhor em relação ao suporte entre navegadores (suporta IE8 e posterior, WebKit e Gecko). A pergunta foi feita: "o código precisa ser compatível com todos os principais navegadores: Internet Explorer 6,7 e 8, Firefox e Safari". Este requisito do navegador x pode ter sido adicionado por Paul Sweatte em 2013 embora ... desculpe se for o caso.
Adrien Seja
3
Se você adicionar text-indent: 0.01px; text-overflow: "";ele vai trabalhar ainda melhor
Ivan
64

O elemento de seleção e seu recurso suspenso são difíceis de estilizar.

Os atributos de estilo para o elemento select de Chris Heilmann confirmam o que Ryan Dohery disse em um comentário à primeira resposta:

"O elemento select faz parte do sistema operacional, não do cromo do navegador. Portanto, é muito pouco confiável para o estilo e não faz sentido tentar de qualquer maneira".

pavium
fonte
47

Eu tive esse problema exato, exceto que não podia usar imagens e não estava limitado pelo suporte ao navegador. Isso deve estar "sob especificação" e, com sorte, começar a trabalhar em qualquer lugar eventualmente .

Ele usa camadas de fundo giradas em camadas para "cortar" uma seta suspensa, pois os pseudoelementos não funcionariam para o elemento selecionado.

Edit: Nesta versão atualizada, estou usando variáveis ​​CSS e um pequeno sistema de temas.

: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
fonte
5
Uau, essa é uma das soluções mais legais que eu já vi. Funciona para mim nas versões mais recentes do Chrome e Safari no Mac. E quanto a outros navegadores?
Tintin81
2
Funciona para mim no Firefox com a adição de-moz-appearance: none;
Zac
45

A maior inconsistência que eu notei ao estilizar as listas suspensas é a renderização Safari e Google Chrome (o Firefox é totalmente personalizável por meio de CSS). Após algumas pesquisas nas profundezas obscuras da Internet, deparei-me com o seguinte, que quase resolve completamente minhas dúvidas com o WebKit:

Correção do Safari e do Google Chrome :

select {
  -webkit-appearance: none;
}

No entanto, isso remove a seta suspensa. Você pode adicionar uma seta suspensa usando uma área próxima divcom fundo, margem negativa ou absolutamente posicionada sobre a lista suspensa selecionada.

* Mais informações e outras variáveis ​​estão disponíveis na propriedade CSS: -webkit-aparecimento .

ioTus
fonte
1
Não se esqueça de adicionar seu estilo depois disso;) Mas estou muito feliz por ler este comentário hoje.
Teewuane
1
você poderia, por favor, elaborar sua declaração: "O Firefox é totalmente personalizável através de CSS" para mim parece que o firefox não suporta a propriedade de aparência ... então, como isso seria feito no firefox?
19612 Danield
36

<select>as tags podem ser estilizadas por meio de CSS, como qualquer outro elemento HTML em uma página HTML renderizada em um navegador. Abaixo está um exemplo (excessivamente simples) que posicionará um elemento de seleção na página e renderizará o texto das opções em azul.

Exemplo de arquivo 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>

Exemplo de arquivo 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
fonte
30
Incrível, a primeira vez que vi "mães" envolvidas na Internet sem que isso fosse rude. +1 para isso!
BaL
34
Esta resposta não resolve esta questão. Só estilos selecionar a entrada, mas não a lista suspensa
Kyborek
14
Essa resposta ignora totalmente os desafios de criar uma lista suspensa para obter consistência entre navegadores. Esta é uma resposta de esforço muito baixo.
BentOnCoding
18

A postagem do blog Como o estilo suspenso do formulário CSS, nenhum JavaScript funciona para mim, mas falha no Opera :

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

Aqui está uma versão que funciona em todos os navegadores modernos. Está usando a chave appearance:noneque remove a formatação padrão. Como toda a formatação se foi, é necessário adicionar novamente a seta que diferencia visualmente a seleção da entrada.

Exemplo de trabalho: 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
fonte
16

Eu cheguei ao seu caso usando o Bootstrap . Esta é a solução mais simples que funciona:

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: o material base64 está fa-chevron-downem SVG.

Yajo
fonte
12

Nos navegadores modernos, é relativamente simples estilizar o <select>CSS. Com appearance: nonea única parte complicada é substituir a seta (se é isso que você deseja). Aqui está uma solução que usa um data:URI embutido com SVG em texto sem formatação:

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>

O restante do estilo (bordas, preenchimento, cores etc.) é bastante direto.

Isso funciona em todos os navegadores que acabei de experimentar (Firefox 50, Chrome 55, Edge 38 e Safari 10). Uma observação sobre o Firefox é que, se você deseja usar o #caractere no URI de dados (por exemplo fill: #000), precisa escapar dele ( fill: %23000).

Kevin Christopher Henry
fonte
1
Você também pode dimensionar o SVG com o atributo heighte / ou widthna <svg>tag, em vez da propriedade 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;}
lagartixa
fonte
Não é possível selecionar nada com isso no Chrome atual.
Vitaly Zdanevich 11/11
9

Estilos CSS selecionados personalizados

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

Roko C. Buljan
fonte
Um pouco mais adaptável (mas não foi testado em todos os navegadores):background-position: right 15px center, right 10px center;
Robin Stewart
8

Use a clippropriedade para cortar as bordas e a seta do selectelemento e adicione seus próprios estilos de substituição ao 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>

Use uma segunda seleção com opacidade zero para tornar o botão clicável:

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

As coordenadas diferem entre o Webkit e outros navegadores, mas uma consulta @media pode cobrir isso.

Referências

Paul Sweatte
fonte
1
Trabalhando bem para mim, pelo menos no chrome: position: absolute; clipe: rect (2px 85px 128px 2px); índice z: 2; preenchimento esquerdo: 18 px; padding-right: 18px; margem: 7px automático; cor: # 555; tamanho da fonte: herdar; cor de fundo: transparente;
19712 BrianFreud
1
Achei que cortar a flecha apenas metade funciona no IE7, pois você não tem controle sobre a borda do select.
CpILL
1
Adicionada a funcionalidade de clique como parte de uma pergunta relacionada
Paul Sweatte
1
@PaulSweatte, uau, este é o seu vigésimo necromante ! Parabéns. Você também superou todas as minhas consultas para obter um distintivo de necromante de ouro .
Nemo
5

Um exemplo muito bom que usa :aftere :beforefaz o truque está em Styling Select Box with CSS3 | CSSDeck

Ahmad Ajmi
fonte
1
Sim, mas exigência em questão foi deve compatível com Internet Explorer 6,7 e 8
Jitendra Vyas
2
Sim Não é compatível com o IE, mas adorei compartilhar para quem procura uma solução moderna como estava procurando.
Ahmad Ajmi
5

Editar este elemento não é recomendado, mas se você quiser tentar, é como qualquer outro elemento HTML.

Editar exemplo:

/* 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
fonte
2
@ MikkoP: ao sugerir edições, você poderia fornecer um resumo de edição mais descritivo? "Melhorou a mensagem" não é muito útil como um resumo de alto nível para nós, revisores. Obrigado.
Jean-François Corbett
1
@ Jean-FrançoisCorbett Vou tentar ser mais específico :)
MikkoP
1
você não pode estilizar elementos de opção (consulte esta resposta do SO: stackoverflow.com/a/7208814/703717 ) #
Danield 19/12/12
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;
}

Isso usa uma cor de fundo para selecionar elementos e eu removi a imagem.

Por sorte
fonte
4

Sim. Você pode estilizar qualquer elemento HTML pelo nome da tag, assim:

select {
  font-weight: bold;
}

Obviamente, você também pode usar uma classe CSS para estilizá-la, como qualquer outro elemento:

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

<style type="text/css">
  .important {
    font-weight: bold;
  }
</style>
Dave Ward
fonte
6
Eu não estou falando assim, eu quero mudar a seta suspensa para outra coisa
Jitendra Vyas
5
Você não pode estilizar a seta suspensa para outra imagem, ela é controlada pelo sistema operacional. Se você realmente precisar, sua melhor aposta é usar um widget suspenso DHTML.
22911 Ryan Doherty
3
Você só pode alterar propriedades de CSS por meio de CSS. Você pode alterar sua margem, preenchimento, propriedades de fonte, cor de plano de fundo etc. Se quiser fazer com que pareça completamente diferente, basicamente é necessário substituí-lo por gráficos em tempo de execução via JavaScript (o que não é uma solução terrível se for bem-sucedido) )
Dave Ward
4

Aqui está uma solução baseada nas minhas idéias favoritas desta discussão. Isso permite estilizar um elemento <select> diretamente sem nenhuma marcação adicional.

Ele funciona no Internet Explorer 10 (e posterior) com um fallback seguro para o Internet Explorer 8/9. Uma ressalva para esses navegadores é que a imagem de plano de fundo deve ser posicionada e ser pequena o suficiente para se esconder atrás do controle de expansão 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

ralgh
fonte
3

Existe uma maneira fácil.

Verifique este violino e perdoe-me o excesso de estilos: https://jsfiddle.net/dkellner/7ac9us70/

O truque por trás: assim que a tag <select> obtiver uma propriedade chamada "size", ela se comportará como uma lista de altura fixa e, de repente, por algum motivo, permitirá que você a impeça. Agora, estritamente falando, a lista fixa é um efeito colateral - mas apenas nos ajuda mais porque a usamos para a "aparência suspensa".

Um exemplo mínimo:

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

(para simplificar, eu fiz isso com o jQuery - mas você pode fazer o mesmo sem ele)

Notas laterais

  • Esta solução oferece mais do que apenas uma seleção: o valor também é editável manualmente. Use a propriedade readonly se você preferir a maneira restrita à seleção padrão.

  • Para maximizar as possibilidades de estilo, as tags <optgroup> não estão próximas dos filhos, elas são movidas antes deles. É intencional, visualmente mais claro e eles ficam felizes em trabalhar assim, não se preocupe.

  • Javascripts: sim, eu sei que o OP disse "sem Javascript", mas entendi como não se preocupe com plugins , o que é bom. Você não precisa de bibliotecas para esta. Nem o jQuery, como eu disse, é apenas pela clareza do exemplo.

dkellner
fonte
2

Você definitivamente deve fazê-lo como em Styling select, optgroup e options with CSS . De várias maneiras, cor de plano de fundo e cor são exatamente o que você normalmente precisa para estilizar as opções, não a seleção inteira.

Otvazhnii
fonte
2

Você também pode adicionar um estilo de foco instantâneo ao menu suspenso.

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>


fonte
2

O terceiro método na resposta de Danield pode ser aprimorado para trabalhar com efeitos de foco e outros eventos de mouse. Apenas certifique-se de que o elemento "botão" venha logo após o elemento de seleção na marcação. Em seguida, direcione-o usando o seletor + CSS:

HTML:

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

CSS:

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

No entanto, isso mostrará o efeito de foco ao passar o mouse sobre qualquer lugar sobre o elemento de seleção, não apenas sobre o "botão".

Estou usando esse método em combinação com Angular (desde que meu projeto seja um aplicativo Angular de qualquer maneira), para cobrir todo o elemento select e permitir que o Angular exiba o texto da opção selecionada no elemento "button". Nesse caso, faz todo o sentido que o efeito de passar o mouse se aplique ao passar o mouse em qualquer lugar sobre a seleção.

Porém, ele não funciona sem JavaScript; portanto, se você quiser fazer isso, e seu site precisar funcionar sem JavaScript, verifique se o script adiciona os elementos e classes necessários para o aprimoramento. Dessa forma, um navegador sem JavaScript simplesmente obterá uma seleção normal, sem estilo, em vez de um emblema estilizado que não é atualizado corretamente.

Adrian Schmidt
fonte
1
Eu adoraria saber o motivo de quaisquer votos negativos, para que eu possa melhorar! Adr
Adrian Schmidt
1

Uma solução apenas CSS e HTML

Parece compatível com Chrome, Firefox e Internet Explorer 11. Mas, por favor, deixe seus comentários sobre outros navegadores da web.

Conforme sugerido pela resposta de Danield, envolvo meu select em uma div (até duas divs para compatibilidade com o navegador x) para obter o comportamento esperado.

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

Observe os dois wrappers div.

Observe também a div extra adicionada para colocar o botão de seta para baixo onde quiser (posicionado absolutamente), aqui o colocamos à esquerda.

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
fonte