Pedido de feedback de desenvolvedor: seleção personalizável

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:

Estilo de user agent padrão para seleção personalizável à direita. Isso está sujeito a mudanças e adoraríamos receber seu feedback.
Demonstração de uma seleção básica em comparação com uma seleção personalizável.

Como as partes se encaixam

Diagrama mostrando partes de uma seleção.

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:

Todo o conteúdo de texto no option é renderizado na versão padrão do elemento de seleção.

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.

Mudar os estilos de várias partes da seleção com o botão padrã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>
Seletor de país com sinalizações.

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>
Captura de tela do seletor de moeda.

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;
}
Seleção no estilo do Gmail com um ícone que representa a opção selecionada.

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);
}
Seleção interativa no estilo do Gmail com conteúdo mostrado progressivamente ao passar o cursor ou em foco.

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.