Publicado em: 14 de agosto de 2025
Com o fim da temporada de eventos do Google I/O, esta postagem resume os principais destaques de CSS e interface da Web compartilhados nos nossos eventos deste ano.
Recursos incrivelmente poderosos que os desenvolvedores só sonhavam em ter chegaram aos navegadores e estão alcançando a compatibilidade entre navegadores mais rápido do que nunca. No entanto, apesar desse progresso, alguns dos padrões de interface mais comuns ainda são surpreendentemente difíceis de implementar corretamente. Muitas vezes, é preciso usar frameworks JavaScript, truques complexos de CSS e muito código personalizado para criar componentes que deveriam ser mais simples.
A equipe do Chrome, em colaboração com outros fornecedores de navegadores, órgãos de padrões como o CSSWG e o WHATWG, e grupos da comunidade como o Open UI, está focando em tornar esses padrões fundamentais de interface do usuário genuinamente simples de implementar.
Menus de seleção personalizáveis
O elemento <select>
é essencial para formulários, mas a estrutura interna dele sempre foi protegida pelo navegador, o que torna quase impossível um estilo CSS consistente e abrangente. Para criar um <select>
melhor, é preciso entender os blocos de construção dele: a API Popover e a API CSS Anchor Positioning.
A API Popover: agora na Baseline
Um menu suspenso personalizado precisa de uma caixa flutuante de opções que apareça acima de todos os outros elementos da interface, seja fácil de dispensar e gerencie o foco corretamente. A API Popover processa tudo isso e, desde este ano, atingiu o status "Recém-disponível" do Baseline, o que significa que ela está estável em todos os principais navegadores.
Para criar um popover, são necessárias duas partes: um elemento de acionamento (como um <button>
) e o próprio elemento popover. Conecte-os ao popover um id
e o atributo [popover]
. Em seguida, faça referência a esse id
no atributo [popovertarget]
do botão.
A API Popover gerencia todo o ciclo de vida do elemento, fornecendo:
- Renderização da camada superior: não é mais necessário lutar com o Z-index.
- Recursos opcionais de dispensa leve: fecha quando um usuário clica fora da área do popover.
- Gerenciamento automático de foco: o navegador lida com a navegação por guias dentro e fora do popover.
- Vinculações acessíveis: o modelo de interação subjacente é processado de forma nativa.
O elemento <dialog>
recebe um upgrade
Embora o popover seja uma ferramenta poderosa, nem sempre é a escolha certa. Por exemplo, em interações de bloqueio de página que exigem feedback do usuário, um modal <dialog>
é mais adequado.
Antes, o <dialog>
não tinha algumas das conveniências do [popover]
, mas isso está mudando. Com o novo atributo closedby="any"
, as caixas de diálogo modais agora oferecem suporte à funcionalidade de dispensa leve, fechando quando o usuário clica fora ou pressiona a tecla "Esc".
Além disso, os invocadores de comandos ([command]
e [commandfor]
) oferecem uma maneira declarativa e sem JavaScript de conectar um botão a uma ação, como abrir uma caixa de diálogo com command="show-modal"
.
Elemento <dialog> + closedby=any + invocadores de comandos |
[popover] atributo |
|
---|---|---|
Uso principal | Interação modal (contratos de usuário, tutoriais etc.) | Interface temporária (menus, dicas, cards, alertas de toast) |
Descartável com um toque | Sim | Sim |
Prende o foco | Sim | Não |
Página "Inertes" | Sim | Não |
Ativação declarativa | Sim | Sim |
Implementação | Elemento | Atributo |
Renderiza na camada superior | Sim | Sim |
Totalmente estilizado | Sim | Sim |
Posicionamento de âncora do CSS
Quando um popover aparece, ele precisa ser posicionado em relação ao elemento que o abriu. Calcular isso manualmente com JavaScript é frágil e pode prejudicar a performance.
A partir do Chrome 125, você pode usar a API CSS Anchor Positioning. Essa nova capacidade vincula declarativamente um elemento a outro, processando automaticamente o reposicionamento quando ele se aproxima da borda da tela. Esse recurso faz parte da Interop 2025, uma iniciativa entre navegadores para lançar recursos muito solicitados. Isso significa que ele estará disponível em todos os principais navegadores até o final de 2025.

Embora seja possível vincular elementos explicitamente com as propriedades anchor-name
e position-anchor
, uma atualização na especificação e no Chrome 133 cria uma relação de âncora implícita entre um <popover>
e o <button>
de invocação dele. Isso simplifica muito o código e significa que agora você pode posicionar o popover com uma única linha de CSS, como: position-area: bottom span-left
.
A ferramenta de âncora do chrome.dev mostra como usar position-area
para conseguir o posicionamento desejado:
Vá além e faça com que o navegador reposicione suas âncoras, evitando que elas saiam da tela, definindo substitutos com position-try-fallbacks
. A demonstração a seguir mostra um popover que usa essa propriedade para lógica de reposicionamento integrada:
Um <select>
verdadeiramente personalizável
Com esses blocos de construção em versões anteriores, o estilo nativo da Web para elementos <select>
finalmente chegou ao Chrome 134. Isso inclui uma nova propriedade appearance
, novos pseudoelementos e o elemento <selectedcontent>
.
Para desbloquear a personalização, aplique appearance: base-select;
ao elemento <select>
e ao novo pseudoelemento ::picker(select)
, que segmenta a lista suspensa de opções. Isso expõe novas partes internas para estilização, incluindo:
<selectedcontent>
: representa o conteúdo da opção selecionada mostrada no botão.::picker-icon
: o ícone de seta suspensa<option>:checked
e::checkmark
: para estilizar a opção selecionada e o indicador de marca de seleção.

Isso permite conteúdo avançado nas opções e controle refinado sobre a exibição. Por exemplo, é possível mostrar um ícone e um subtítulo na lista de opções, mas ocultá-los no estado fechado usando display: none
em selectedcontent
.
O melhor é que essa API pode ser aprimorada progressivamente. Em navegadores que não oferecem suporte a esses recursos, os usuários ainda recebem uma seleção funcional nativa da Web. Você tem uma aparência personalizada, preservando a acessibilidade integrada, a navegação por teclado e a integração de formulários do elemento de seleção nativo da Web.
Carrosséis
Os carrosséis estão em toda a Web, não apenas nas seções principais. Isso inclui conteúdo rolável horizontalmente em layouts compactos, como uma interface de loja de apps. Mas criar carrosséis na Web ainda é difícil, com muitas considerações, como gerenciamento de estado, instabilidade de rolagem, interatividade e acessibilidade. Mas, se você pensar bem, os carrosséis são essencialmente áreas de rolagem sofisticadas com mais recursos de interface.
Como começar a usar scrollers
Para criar um carrossel, comece com uma lista de itens que transbordam do contêiner. Para ocultar a barra de rolagem horizontal e manter o conteúdo rolável, use scrollbar-width: none
. Além disso, para que o rolador pareça "rápido", aplique scroll-snap-type
e scroll-snap-align
, o que garante que os itens se encaixem no lugar à medida que o usuário rola a tela.
Anterior e próxima com um ::scroll-button
O novo pseudoelemento ::scroll-button()
, que chegou ao Chrome 135, instrui o navegador a gerar botões "próximo" e "anterior" com estado e acessíveis. O navegador processa automaticamente as funções ARIA corretas, a ordem de tabulação e até mesmo desativa os botões quando você chega ao início ou ao fim, tudo sem JavaScript adicionado.
Para iniciar os botões de rolagem, dê a eles conteúdo e um rótulo acessível, assim:
.carousel {
&::scroll-button(left) {
content: "⬅" / "Scroll Previous";
}
&::scroll-button(right) {
content: "⮕" / "Scroll Next";
}
}

Aplique um estilo a esses botões e posicione-os em relação ao carrossel pai com o posicionamento de âncora CSS, que é a abordagem recomendada.
Navegação direta com ::scroll-marker
Para indicadores de pontos ou miniaturas, os pseudoelementos ::scroll-marker
e ::scroll-marker-group
associam marcadores de navegação diretamente aos itens no contêiner de rolagem. O navegador trata o grupo como um tablist
e processa a navegação pelo teclado.
Semelhante aos botões de rolagem, inicie os marcadores de rolagem ativando a propriedade content
e forneça um rótulo acessível. No exemplo a seguir, um atributo de dados é usado para definir o rótulo do marcador de rolagem. Além disso, posicione os marcadores de rolagem no ::scroll-marker-group
usando a propriedade scroll-marker-group
. Por fim, estilize o marcador ativo usando a nova pseudoclasse :target-current
. Confira um exemplo de como isso pode aparecer em um carrossel básico:
.carousel {
scroll-marker-group: after;
> li::scroll-marker {
content: ''/ attr(data-name);
}
> li::scroll-marker:target-current {
background: blue;
}
}

Consultas de estado de rolagem
Com os novos recursos CSS relacionados à rolagem, é possível criar carrosséis mais dinâmicos e interativos. A consulta de estado de rolagem é uma nova media query que é aplicada com base no estado de um scroller. Há três tipos diferentes de consultas de estado de rolagem, que podem ser acessadas usando scroll-state()
em uma instrução @container
. São eles:
scroll-state(snapped)
: corresponde quando um elemento está na posição "ajustada". Em carrosséis, é quando ele está encaixado no centro.scroll-state(stuck)
: estiliza um elemento, como um cabeçalho, quando o elemento pai fica fixo.scroll-state(scrollable)
: adicione indicadores visuais, como um efeito de fade, para mostrar que há mais conteúdo para rolar.
Resumo geral
Uma combinação de novas primitivas de carrossel CSS, consultas de estado de rolagem e posicionamento de âncora facilita a criação de carrosséis personalizados e interativos. Vá além e incorpore animações controladas por rolagem para vincular animações diretamente à posição de rolagem, criando efeitos eficientes, como itens que aumentam e desaparecem à medida que rolam para a visualização. Essas animações são executadas fora da linha de execução principal, proporcionando uma experiência suave.
Esse carrossel interativo combina consultas scroll-state()
, ::scroll-button
, ::scroll-marker
, posicionamento de âncora CSS e :target-current
.
Além disso, você pode usar uma nova propriedade chamada interactivity
para ajudar os usuários a se concentrarem no conteúdo ativo. interactivity: inert
permite que o usuário aplique a inércia usando CSS, tornando os itens do carrossel fora da tela não focalizáveis e removendo-os da árvore de acessibilidade.
Saiba mais sobre os carrosséis do CSS.
Hovercards interativos
Os cards flutuantes, que são os pop-ups avançados que aparecem quando você passa o cursor sobre um nome de usuário ou link, são muito úteis, mas notoriamente difíceis de criar corretamente. Acertar os atrasos, o processamento de eventos e o suporte a vários dispositivos pode levar meses para uma equipe dedicada. Mas estamos trabalhando em uma nova solução declarativa que deve resolver esse problema de uma vez por todas.
Popovers acionados por interesse com [interestfor]
O principal recurso por trás dos cards flutuantes declarativos é o atributo [interestfor]
. Esse recurso vai trazer o poder dos popovers, mas vai acioná-los com base no "interesse" do usuário. Por exemplo, o interesse do usuário em um dispositivo apontador seria um passar o cursor, uma navegação por guias com um teclado ou um toque longo ou um toque em telas sensíveis ao toque. A interação em dispositivos móveis ainda não foi resolvida.
Para converter um popover baseado em cliques em um baseado em interesses, crie um elemento de invocação, que pode ser um <button>
ou um <a>
, e atribua a ele um atributo [interestfor]
igual ao id
do elemento [popover]
. Ela tem esta aparência em HTML:
<button interestfor="profile-callout">
...
</button>
<div id="profile-callout" popover>
...
</div>
O navegador processa toda a lógica de eventos complexos, incluindo:
- Eventos de entrada e saída:entrada por passar o cursor em dispositivos de ponteiro fino, navegação por guias com teclado, pressionamento longo ou toque em dispositivos de ponteiro grosso.
- Atrasos de eventos:controle os atrasos de entrada e saída com uma única propriedade CSS.
Esse recurso é compatível com outros recursos de popover, como suporte à camada superior, em que o popover é renderizado em uma nova camada acima do restante da árvore DOM. As vinculações de componentes semânticos e o modelo de árvore de acessibilidade subjacente são processados de forma nativa.
Estilizar invocadores de interesse
Os invocadores de interesse incluem alguns novos recursos. Uma delas é a capacidade de controlar os atrasos de entrada e saída usando uma propriedade CSS: interest-target-delay
. A outra é a capacidade de estilizar o elemento de invocação com base em se ele tem interesse ou não, usando a pseudoclasse :has-interest
.
[interesttarget] {
interest-target-delay: 0s 1s;
&:has-interest {
background: yellow;
}
}
popover="hint"
e interface multifuncional
Uma peça fundamental do quebra-cabeça para invocadores de interesse é um novo tipo de popover: popover="hint"
. A principal diferença de outros popovers é que um popover de dica não fecha outros popovers quando é aberto. Isso é perfeito para dicas ou cards de prévia que precisam aparecer sem dispensar um menu ou uma janela de chat já aberta.
Browser Support
popover=auto | popover=manual | popover=hint | |
---|---|---|---|
Dispensar leve (clicando fora ou usando a tecla esc ) | Sim | Não | Sim |
Fecha outros elementos popover=auto quando aberto | Sim | Não | Não |
Fecha outros elementos popover=hint quando aberto | Sim | Não | Sim |
Fecha outros elementos popover=manual quando aberto | Não | Não | Não |
É possível abrir e fechar o popover com JS (showPopover() ou hidePopover() ) | Sim | Sim | Sim |
Gerenciamento de foco padrão para a próxima parada de tabulação | Sim | Sim | Sim |
Pode ocultar ou alternar com popovertargetaction | Sim | Sim | Sim |
Pode ser aberto no elemento pai popover para manter o elemento pai aberto | Sim | Sim | Sim |
Isso permite criar de forma declarativa interfaces multifuncionais e eficientes. Agora, um único botão pode ter um popover automático usando popovertarget
para a ação de clique principal (como abrir um painel de notificações) e um popover de dica invocada por interesse para mostrar uma dica útil ao passar o cursor.
O futuro é declarativo
Os recursos abordados aqui representam uma mudança fundamental para uma plataforma da Web mais eficiente e declarativa. Ao deixar que o navegador lide com o trabalho complexo e repetitivo de gerenciamento de estado e acessibilidade, podemos remover montanhas de JavaScript, melhorar o desempenho e nos concentrar no que fazemos de melhor: criar experiências de usuário inovadoras e envolventes. Esta é realmente uma era de ouro para a interface da Web, e ela está apenas começando. Acompanhe aqui mesmo enquanto trabalhamos para criar uma Web mais eficiente e fácil de usar.
Outros recursos: