O estilo dos controles de formulário, como o elemento <select>
, é um dos principais problemas dos desenvolvedores há anos, e estamos trabalhando em uma solução. Embora esse trabalho seja complexo e tenha demorado muito para ser concluído, estamos chegando perto de lançar esse recurso. Uma versão personalizável do elemento de seleção está oficialmente na etapa 2 do WHATWG, com forte interesse em vários navegadores e um protótipo para você testar no Chrome Canary 130.
Teste e envie seu feedback
Verifique se a instalação do Chrome Canary está atualizada para a versão 130 e se a flag "Recursos experimentais da plataforma da Web" está ativada. Para ativar essa sinalização, acesse chrome://flags na barra de endereço e ative #experimental-web-platform-features. As demonstrações do Codepen aparecem nesta postagem. Outra opção é conferir esta coleção do Codepen (link em inglês) para ver todas em um só lugar.
Use este formulário para enviar feedback sobre o recurso. Ela leva apenas três minutos.
Vamos nos aprofundar nos recursos da API de seleção personalizável, que se baseia na tag HTML select atual.
Ativação do novo <select>
Para ativar o novo comportamento, use a propriedade appearance
do CSS no botão de seleção na página e também no seletor de seleção. Para ativar, defina appearance: base-select
no elemento <select>
e no ::picker(select)
.
::picker(select)
é um novo pseudoelemento fornecido pelo user agent que se aplica apenas a elementos <select>
que foram ativados para o novo comportamento usando appearance: base-select
. Esse pseudoelemento seletor é o pop-up acionado pelo botão de seleção básica. É possível ativar ambos conforme mostrado no código a seguir:
select,
::picker(select) {
appearance: base-select;
}
Você pode ativar apenas o botão in-page, mas não é possível ativar apenas o pop-up do seletor sem ativar o botão in-page. O ::picker(select)
só é criado quando o appearance: base-select
é aplicado ao <select>
.
Agora você pode personalizar o elemento de seleção. A nova seleção personalizável vem com alguns estilos padrão que têm a mesma aparência em navegadores e sistemas operacionais. Confira como o seletor personalizado padrão se parece com o seletor existente no Chrome no macOS:
Como as partes se encaixam
Quando você está no novo modo de seleção personalizável, os novos elementos a que você tem acesso incluem:
- selectedoption
: reflete o HTML interno da opção selecionada no momento.
- option::before
: contém uma marca de seleção para indicar a opção selecionada como uma affordance de acessibilidade padrão (sujeito a alterações).
- ::picker(select)
: pop-up que contém todo o conteúdo fora de button
dentro de um select personalizável.
É possível estilizar qualquer parte da seleção. Por exemplo, é possível adicionar conteúdo não interativo arbitrário nos elementos <option>
, definir o estilo do botão na página que abre o menu suspenso de seleção e definir o estilo da lista suspensa de opções (::picker(select)
).
Também é possível estilizar o button
, o indicador de seta "traga sua própria seta" e adicionar conteúdo arbitrário dentro e ao redor de qualquer um dos elementos. Além de adicionar conteúdo, você pode ocultar qualquer um desses novos elementos e estilos padrão. Por exemplo, se você não quer uma marca de seleção indicadora no pseudoelemento ::before da opção, use o CSS a seguir.
/* Remove the default checkmark from the selected option */
option::before {
display: none;
}
Embora possa haver um número ilimitado de elementos dentro da seleção, o navegador agrupa tudo fora de um elemento <button>
no pseudoelemento ::picker(select)
, que se comporta como um pop-up ancorado ao botão. Esse <button>
ativa o ::picker(select)
. As opções e outros elementos diretamente dentro do select serão elevados para o ::picker(select)
, ou você pode trazer seu próprio wrapper para fins de estilização. Esse wrapper também será colocado dentro do pseudoelemento ::picker(select)
.
<select>
<button>
<selectedoption></selectedoption>
</button>
// Everything else that will go into the ::picker(select) popover
</select>
A nova <select>
personalizável usa as funcionalidades de popover e posicionamento âncora. Ele é criado com essas duas tecnologias. Isso significa que a lista suspensa de opções em um select age como um pop-over ancorado ao botão de gatilho que abre a seleção.
Você pode usar o posicionamento da âncora para estilizar esse pop-over ::picker(select)
, inclusive como torná-lo ancorado a outros elementos. Esse modelo de conteúdo também significa que os estilos de animação da camada superior funcionam com a lista de opções para animar os efeitos de entrada e saída.
Melhorar o elemento <select>
Anteriormente, a equipe do Chrome estava trabalhando na ideia de um elemento <selectlist>
. O que é descrito nesta postagem é que o recurso foi redesenhado para reutilizar o elemento <select>
.
Um dos principais benefícios de reutilizar o elemento <select>
existente é a capacidade de aprimorar progressivamente o elemento HTML básico. Em comparação com um elemento totalmente novo, a reutilização de <select>
ainda renderiza conteúdo significativo na página. O exemplo a seguir mostra a seleção personalizada em comparação com o que um usuário em um navegador incompatível veria:
Estilo básico
As mudanças podem ser tão simples quanto o estilo visual do elemento de seleção. Por exemplo, para atualizar os estilos de botão, passe o cursor e os estilos de foco ou o plano de fundo das opções de seleção. Depois de ativar a appearance: base-select
, aplique o CSS que quiser às partes da seleção.
Para personalizar o indicador de seta, adicione seu próprio botão e seta dentro da seleção.
<select>
<button>
<selectedoption></selectedoption>
<span>
// Arrow here
</span>
</button>
// Everything else that will go into the ::picker(select) popover
</select>
Em seguida, defina o estilo da seta:
/* style the arrow */
button span {
/* arrow styles */
transition: rotate 0.2s;
}
/* adjust arrow styles when the picker is open */
select:open button span {
rotate: -180deg;
}
Conteúdo complexo nas opções
Vá além com a capacidade de adicionar e estilizar conteúdo além de strings nos elementos <option>
dentro de <select>
. Um exemplo básico é adicionar imagens de bandeiras ao lado dos nomes dos países em um menu suspenso. Para fazer isso, adicione um elemento de imagem ao lado do texto da opção.
<option value="france">
<img src="img/flag_of_france.svg" alt="" />
<span>France</span>
</option>
Um exemplo mais complexo pode incluir fotos de perfil, nomes e informações alternativas para ajudar você a decidir qual item selecionar no menu suspenso.
<option value="eur">
<img src="euro-flag.png" alt="" />
<div class="currency">
<div class="currency-short">EUR</div>
<div class="currency-long">Euro</div>
</div>
<div class="symbol" aria-hidden="true">€</div>
</option>
Estilo da opção selecionada
Talvez você queira que a opção selecionada seja exibida de maneira diferente no estado selecionado do que no menu suspenso. Um exemplo disso é a interface do Gmail, em que, para economizar espaço, o rótulo é removido quando a opção é selecionada. Faça isso vinculando o elemento <selectedoption>
ao estilo. O <option>
contém todas as marcações abaixo:
<option value="reply-all">
<img class="material-symbol" src="material-symbol-reply.png">
<span class="text">Reply all</span>
</option>
Agora, aplique display: none
em .text
dentro de <selectedoption>
' para ocultar o conteúdo do texto e mostrar apenas o ícone:
selectedoption .text {
display: none;
}
Opções interativas
Com controle total sobre o estilo do ::picker(select)
, crie a demonstração anterior para torná-la interativa ao passar o cursor e focar. Nesta demonstração, a nova função calc-size() é usada para animar a largura do seletor, desde a exibição dos ícones até a exibição da largura total das opções ao passar o cursor ou se o seletor tiver uma opção com foco visível.
/* base styles when picker is open but not interacted with */
::picker(select) {
width: var(--icon-width);
transition: width 0.5s;
}
/* animate the text in on hover & focus */
::picker(select):hover,
select:has(option:focus-visible)::picker(select) {
/* auto width! */
width: calc-size(auto, size + 0.5rem);
}
Limitações e observações sobre acessibilidade
Com grandes poderes, vêm grandes responsabilidades. Para manter tudo acessível, o recurso tem algumas limitações.
- Além dos elementos
<option>
, nenhum elemento interativo (focalizável) é permitido dentro do<select>
, como botões ou outros elementos. Por enquanto, o modelo de conteúdo proposto permite apenas os elementos<div>
,<span>
,<option>
,<optgroup>
,<img>
,<svg>
e<hr>
. - Os botões divididos estão na fase de experimentação enquanto trabalhamos em uma solução acessível.
No futuro, o modelo de conteúdo deve ser expandido para ser mais flexível, à medida que a história sobre acessibilidade para essas experiências é elaborada.
Conclusão
Estamos animados para ver o progresso desse recurso por meio de grupos de trabalho e órgãos de padronização e compartilhar nosso progresso à medida que construímos ativamente o protótipo e avaliamos a forma desse recurso. Se algo não funcionar como esperado, informe-nos.
Embora esse recurso ainda esteja em desenvolvimento, adoraríamos receber seu feedback por meio deste breve formulário de feedback.
Agradecemos por nos ajudar a fazer isso da maneira correta e facilitar a criação de controles de formulários acessíveis e personalizáveis na Web.