problema com <select> e: depois com CSS no WebKit


123

Gostaria de adicionar algum estilo em uma caixa de seleção com o pseudo: after (para estilizar minha caixa de seleção com 2 partes e sem imagens). Aqui está o HTML:

<select name="">
  <option value="">Test</option>
</select>

E isso não funciona. Não sei por que e não encontrei a resposta nas especificações do W3C. Aqui está o CSS:

select {
  -webkit-appearance: none;
  background: black;
  border: none;
  border-radius: 0;
  color: white;
}

select:after {
  content: " ";
  display: inline-block;
  width: 24px; height: 24px;
  background: blue;
}

Então é normal ou existe um truque?


Imagino que isso não seria, não deveria ser possível, caso contrário, seria muito fácil alterar o conteúdo dos formulários. Imagine um pouco de CSS alterando o preço de exibição de alguma coisa. Pode ser mostrado como mais barato do que realmente é, levando as pessoas a comprarem algo por mais do que esperavam. (Ou claro que, se alguém tem acesso ao CSS de uma página / userstylesheet, em seguida, eles provavelmente poderia fazer o mesmo de outras maneiras ...)
Synetech

22
@ Synetech - Isso está incorreto, o autor da página deve ter controle total sobre todos os aspectos do estilo da página. Os fabricantes de navegadores que tentam impedir o estilo de certos elementos, porque eles podem ser usados ​​para enganar os usuários, não serão eficazes, pois há um número quase ilimitado de maneiras de enganar o sistema ou produzir falsos positivos.
Jonathan Cross

1
Possível duplicado de pseudo elementos e tag Selecionar
Tessa

Respostas:


132

Não verifiquei isso extensivamente, mas tenho a impressão de que isso ainda não é possível, devido à maneira como os selectelementos são gerados pelo sistema operacional no qual o navegador é executado, e não pelo próprio navegador.


62
É 2019 agora e continua o mesmo #
Placido

40
É 2020 agora e ainda é o mesmo
Joeri Minnekeer 07/01

3
Se eu tivesse visto seu comentário sobre este post de 10 anos de uma hora atrás, teria me economizado uma hora do meu tempo. : C
ericek111 7/01

66

Eu estava procurando a mesma coisa, pois o fundo do meu select é igual à cor da seta. Como mencionado anteriormente, ainda é impossível adicionar qualquer coisa usando: before ou: after em um elemento select. Minha solução foi criar um elemento wrapper no qual adicionei o seguinte: before code.

.select-wrapper {
    position: relative;
}

.select-wrapper:before {
    content: '\f0d7';
    font-family: FontAwesome;
    color: #fff;
    display: inline-block;
    position: absolute;
    right: 20px;
    top: 15px;
    pointer-events: none;
}

E esse meu seleto

select {
    box-sizing: border-box;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    width: 100%;
    padding: 10px 20px;
    background: #000;
    color: #fff;
    border: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
}

select::-ms-expand {
    display: none;
}

Eu usei o FontAwesome.io para minha nova seta, mas você pode usar o que quiser. Obviamente, essa não é uma solução perfeita, mas, dependendo de suas necessidades, pode ser suficiente.


4
Isso é visualmente perfeito. Mas você não pode clicar nesse ícone e selecionar o elemento que não abrirá: / Alguma sugestão?
Schovi 29/06

11
eventos-ponteiro: nenhum; deve cuidar disso. Houve um problema com meu código acima. Vou mudar qualquer sass acima para css para remover qualquer confusão.
sroy

Importa qual pseudo-seletor (antes vs depois) é usado?
Eddegroves

Você pode usar um ou outro
sroy

2
Esta é uma ótima solução, mas ao implementá-la, descobri que, por algum motivo: antes do trabalho e NÃO: depois. Não sei porque.
21815 Lee Probert

31

Para a minha experiência, simplesmente não funciona, a menos que você esteja disposto a embrulhá-lo <select>em algum invólucro. Mas o que você pode fazer é usar a imagem de fundo SVG. Por exemplo

    .archive .options select.opt {
    -moz-appearance: none;
    -webkit-appearance: none;
    padding-right: 1.25EM;
    appearance: none;
    position: relative;
    background-color: transparent;
    background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' version='1.1' height='10px' width='15px'%3E%3Ctext x='0' y='10' fill='gray'%3E%E2%96%BE%3C/text%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-size: 1.5EM 1EM;
    background-position: right center;
    background-clip: border-box;
    -moz-background-clip: border-box;
    -webkit-background-clip: border-box;
}

    .archive .options select.opt::-ms-expand {
        display: none;
    }

Apenas tome cuidado com a codificação de URL adequada por causa do IE. Você deve usar charset=utf8(não apenas utf8), não usar aspas duplas (") para delimitar os valores dos atributos SVG, use apóstrofos (') para simplificar sua vida. Codifique URL s (% 3E). Caso você precise imprimir qualquer caractere não ASCII que você precise obter sua representação UTF-8 (por exemplo, o BabelMap pode ajudá-lo com isso) e depois forneça essa representação no formato codificado por URL - por exemplo, para a U+25BErepresentação UTF-8 ( BLACK ( BLACK DOWN-POINTING SMALL TRIANGLE) \xE2\x96\xBEque é %E2%96%BEquando codificado em URL.


1
Esta é uma solução agradável e elegante #
1937 JosFabre

1
Esta é uma solução fantástica, simples e elegante que não requer HTML extra, exatamente o que eu estava procurando! Obrigado! Esta deve ser a resposta escolhida IMO.
KyleFarris


13

Enfrentou o mesmo problema. Provavelmente poderia ser uma solução:

<select id="select-1">
    <option>One</option>
    <option>Two</option>
    <option>Three</option>
</select>
<label for="select-1"></label>

#select-1 {
    ...
}

#select-1 + label:after {
    ...
}

Você pode adicionar os estilos necessários para fazer com que o rótulo fique sobre o elemento selecionado?
bafromca

7

Esta solução é semelhante à do sroy, mas com triângulo css em vez de fonte da web:

.select-wrapper {
  position: relative;
  width: 200px;
}
.select-wrapper:after {
  content: "";
  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 6px solid #666;
  position: absolute;
  right: 8px;
  top: 8px;
  pointer-events: none;
}
select {
  background: #eee;
  border: 0 !important;
  border-radius: 0;
  -webkit-appearance:none;
  -moz-appearance:none;
  appearance:none;
  text-indent: 0.01px;
  text-overflow: "";
  font-size: inherit;
  line-height: inherit;
  width: 100%;
}
select::-ms-expand {
  display: none;
}
<div class="select-wrapper">
  <select>
    <option value="1">option 1</option>
    <option value="2">option 2</option>
    <option value="3">option 3</option>
  </select>
</div>


6

E se a modificação da marcação não for uma opção?

Aqui está uma solução que não tem requisitos para um wrapper: ele usa um SVG em uma imagem de plano de fundo. Pode ser necessário usar um decodificador de entidade HTML para entender como alterar a cor do preenchimento.

-moz-appearance: none;
-webkit-appearance: none;
appearance: none;

background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%23000000%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E');
background-repeat: no-repeat;
background-position: right .7em top 50%;
background-size: .65em auto;

Comprimido de CSS-Tricks .


Este é um bom truque. Super irritante que ainda não podemos estilizar
seleções

5

Esta é uma solução moderna que eu criei usando uma fonte incrível . As extensões de fornecedor foram omitidas por questões de concisão.

HTML

<fieldset>
    <label for="color">Select Color</label>
    <div class="select-wrapper">
        <select id="color">
            <option>Red</option>
            <option>Blue</option>
            <option>Yellow</option>
        </select>
        <i class="fa fa-chevron-down"></i>
    </div>
</fieldset>

SCSS

fieldset {
    .select-wrapper {
        position: relative;

        select {
            appearance: none;
            position: relative;
            z-index: 1;
            background: transparent;

            + i {
                position: absolute;
                top: 40%;
                right: 15px;
            }
        }
    }

Se o seu elemento de seleção tiver uma cor de plano de fundo definida, isso não funcionará, pois esse fragmento basicamente coloca o ícone da Chevron atrás do elemento de seleção (para permitir que cliques na parte superior do ícone ainda iniciem a ação de seleção).

No entanto, você pode estilizar o wrapper de seleção com o mesmo tamanho do elemento de seleção e estilizar seu plano de fundo para obter o mesmo efeito.

Confira meu CodePen para obter uma demonstração funcional que mostre esse código em uma caixa de seleção com temas escuros e claros, usando um rótulo comum e um marcador de "espaço reservado" e outros estilos de limpeza, como bordas e larguras.

PS Essa é uma resposta que eu havia postado em outra pergunta duplicada no início deste ano.


1
<div class="select">
<select name="you_are" id="dropdown" class="selection">
<option value="0" disabled selected>Select</option>
<option value="1">Student</option>
<option value="2">Full-time Job</option>
<option value="2">Part-time Job</option>
<option value="3">Job-Seeker</option>
<option value="4">Nothing Yet</option>
</select>
</div>

Instando o estilo da seleção porque você não adiciona uma div fora da seleção.

e estilo então em CSS

.select{
    width: 100%;
    height: 45px;
    position: relative;
}
.select::after{
    content: '\f0d7';
    position: absolute;
    top: 0px;
    right: 10px;
    font-family: 'Font Awesome 5 Free';
    font-weight: 900;
    color: #0b660b;
    font-size: 45px;
    z-index: 2;

}
#dropdown{
    -webkit-appearance: button;
       -moz-appearance: button;
            appearance: button;
            height: 45px;
            width: 100%;
        outline: none;
        border: none;
        border-bottom: 2px solid #0b660b;
        font-size: 20px;
        background-color: #0b660b23;
        box-sizing: border-box;
        padding-left: 10px;
        padding-right: 10px;
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.