Estilizando Elementos Select com CSS Moderno
O elemento <select> sempre foi um dos controles de formulário mais resistentes à estilização. Ao contrário de inputs ou botões, ele historicamente era renderizado usando componentes de UI do sistema operacional, o que significa que o CSS só conseguia tocar a superfície. Essa limitação levou desenvolvedores a adotarem soluções alternativas que ainda são comuns em código de produção hoje.
Este artigo cobre ambas as abordagens: a técnica legada amplamente suportada usando appearance: none, e o modelo mais recente appearance: base-select que está emergindo atualmente nos navegadores Chromium modernos.
Pontos-Chave
- Elementos
<select>nativos resistem à estilização porque os navegadores historicamente delegam sua renderização ao sistema operacional, produzindo resultados inconsistentes entre plataformas. - A técnica
appearance: none, combinada com um elemento wrapper e uma seta personalizada viaclip-path, é o método cross-browser mais confiável para estilizar o estado fechado de um select. appearance: base-select(Chrome/Edge 135+) desbloqueia hooks de estilização para o painel dropdown, ícone de seta, marcas de seleção e conteúdo selecionado — mas atualmente apenas em navegadores baseados em Chromium.- Use
@supports (appearance: base-select)para aplicar a abordagem moderna como um aprimoramento progressivo sobre a base legada.
Por Que Elementos <select> Nativos Resistem à Estilização CSS
Navegadores tradicionalmente delegavam a renderização do <select> ao sistema operacional. O resultado era dimensionamento de caixa inconsistente, renderização de fonte e estilos de seta dropdown variados entre Chrome, Firefox, Safari e Edge, sem uma maneira confiável de unificá-los apenas através de CSS.
A lista dropdown aberta (o painel de opções) permanece amplamente não estilizável na maioria dos navegadores até hoje. Essa é uma restrição importante que vale a pena ter em mente antes de escolher sua abordagem.
A Abordagem Legada: appearance: none com um Elemento Wrapper
A técnica de estilização CSS mais amplamente suportada para elementos select envolve três passos:
- Remover a aparência nativa com
appearance: none. - Envolver o
<select>em um elemento container que você pode estilizar livremente. - Adicionar uma seta dropdown personalizada usando
clip-pathou um SVG de background.
:root {
--select-border: #777;
--select-arrow: var(--select-border);
}
select {
appearance: none;
background-color: transparent;
border: none;
padding: 0 1em 0 0;
width: 100%;
font-family: inherit;
font-size: inherit;
cursor: inherit;
line-height: inherit;
outline: none;
}
.select {
display: grid;
grid-template-areas: "select";
align-items: center;
position: relative;
border: 1px solid var(--select-border);
border-radius: 0.25em;
padding: 0.25em 0.5em;
background-color: #fff;
}
select,
.select::after {
grid-area: select;
}
.select::after {
content: "";
width: 0.8em;
height: 0.5em;
background-color: var(--select-arrow);
clip-path: polygon(100% 0%, 0 0%, 50% 100%);
justify-self: end;
pointer-events: none;
}
O truque de sobreposição com CSS grid aqui vale a pena entender: atribuir tanto o <select> quanto o pseudo-elemento ::after à mesma área de grid nomeada os empilha, permitindo que a seta personalizada fique visualmente por cima sem quebrar o comportamento de clique do controle nativo.
Para estados de foco, já que outline no select nativo não se comporta de forma confiável entre navegadores, uma correção comum é adicionar um elemento irmão <span class="focus"> e direcioná-lo com select:focus + .focus usando position: absolute para desenhar um anel de foco visível.
Esta abordagem funciona em todos os navegadores modernos e preserva a acessibilidade nativa — navegação por teclado, anúncios de leitores de tela e envio de formulário se comportam conforme esperado.
Discover how at OpenReplay.com.
A Abordagem Moderna: appearance: base-select
Chrome 135 e Edge 135 introduziram um novo modelo opt-in que expõe partes internas do <select> para estilização CSS direta. Você o ativa assim:
select,
select::picker(select) {
appearance: base-select;
}
Isso desbloqueia vários novos alvos de estilização:
::picker(select)— o painel dropdown contendo opções::picker-icon— o indicador de seta dropdownoption::checkmark— a marca de seleção mostrada ao lado da opção selecionada:open— uma pseudo-classe ativa enquanto o picker está abertooption:checked— direciona a opção atualmente selecionada
Com base-select, você pode estilizar o dropdown picker diretamente, animá-lo abrindo e fechando, e usar o elemento <selectedcontent> para espelhar o conteúdo da opção selecionada no controle fechado. Navegadores que suportam também permitem marcação mais rica dentro das opções quando o modelo de select customizável está habilitado.
Suporte de navegadores: atualmente limitado principalmente a navegadores baseados em Chromium. Verifique o status atual no Can I Use.
Use @supports para aplicá-lo como um aprimoramento progressivo:
@supports (appearance: base-select) {
select,
select::picker(select) {
appearance: base-select;
}
}
Qual Abordagem Você Deve Usar?
appearance: none | appearance: base-select | |
|---|---|---|
| Suporte de navegadores | 95%+ | Limitado (veja tabela de suporte) |
| Estiliza o painel dropdown | Não | Sim |
| Conteúdo rico em opções | Não | Sim |
| Acessibilidade | Nativa | Nativa |
Use a técnica wrapper com appearance: none como sua base. Ela funciona em todos os lugares, preserva acessibilidade e dá a você controle sólido sobre o estado fechado do select. Aplique appearance: base-select por cima com @supports para navegadores que o suportam.
Conclusão
Customizar dropdowns de select HTML com CSS não é mais uma escolha entre “controle total com JavaScript” ou “aceitar os padrões do navegador”. O padrão wrapper com appearance: none permanece como a fundação cross-browser confiável, enquanto appearance: base-select abre a porta para estilizar o painel dropdown, incorporar conteúdo mais rico em opções e animar o picker. A lacuna entre esses dois extremos está se fechando, apenas não uniformemente em todos os navegadores ainda. Comece com a técnica legada, aplique progressivamente a moderna, e você cobrirá a mais ampla gama de usuários com o mínimo de atrito.
Perguntas Frequentes
Não. Definir appearance: none apenas remove a estilização visual fornecida pelo sistema operacional. O elemento HTML select subjacente mantém todo o comportamento nativo de teclado, incluindo navegação por teclas de seta, Enter e Espaço para abrir o dropdown, e Tab para mover o foco. Leitores de tela continuam a anunciar opções corretamente porque a estrutura DOM permanece inalterada.
O suporte para elementos select customizáveis ainda está evoluindo e varia por navegador. Navegadores baseados em Chromium lançaram o recurso primeiro, enquanto outros engines ainda estão implementando-o. Verifique os dados de compatibilidade mais recentes no caniuse.com antes de depender dele em produção, e envolva seus estilos base-select dentro de um bloco @supports (appearance: base-select) para que navegadores não suportados retornem graciosamente aos seus estilos legados.
O elemento select ignora muitas propriedades CSS quando renderizado nativamente. Uma div wrapper dá a você controle total sobre bordas, border-radius, cor de fundo e a seta personalizada via pseudo-elemento. A técnica de sobreposição com grid empilha a seta sobre o select sem interferir com eventos de clique, o que você não consegue alcançar apenas no select.
Use um pseudo-elemento CSS no wrapper com clip-path para desenhar uma forma de triângulo puramente em CSS. Defina pointer-events como none no pseudo-elemento para que os cliques passem através dele para o select abaixo. Alternativamente, você pode usar um SVG inline como background-image no wrapper, codificado como data URI para evitar uma requisição de rede extra.
Truly understand users experience
See every user interaction, feel every frustration and track all hesitations with OpenReplay — the open-source digital experience platform. It can be self-hosted in minutes, giving you complete control over your customer data. . Check our GitHub repo and join the thousands of developers in our community..