Novidades na interface da Web: Recap da I/O 2025

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.

Browser Support

  • Chrome: 114.
  • Edge: 114.
  • Firefox: 125.
  • Safari: 17.

Source

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".

Browser Support

  • Chrome: 134.
  • Edge: 134.
  • Firefox Technology Preview: supported.
  • Safari: not supported.

Source

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".

Browser Support

  • Chrome: 135.
  • Edge: 135.
  • Firefox: behind a flag.
  • Safari Technology Preview: supported.

Source

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.

Browser Support

  • Chrome: 125.
  • Edge: 125.
  • Firefox: not supported.
  • Safari: not supported.

Source

Mostrando como diferentes partes do posicionamento da âncora se correlacionam ao código, como a borda superior da âncora sendo anchor(top) e a borda direita sendo anchor(right).
Diagrama mostrando o posicionamento de âncora do CSS.

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.
Diagrama mostrando novas partes da seleção, como ::picker-icon, selectedcontent e ::picker(select).
Partes da seleção personalizável.

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

Browser Support

  • Chrome: 135.
  • Edge: 135.
  • Firefox: not supported.
  • Safari: not supported.

Source

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";
  }
}
Imagem do carrossel com botões esquerdo e direito
Captura de tela do botão de rolagem simples na demonstração anterior.

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

Browser Support

  • Chrome: 135.
  • Edge: 135.
  • Firefox: not supported.
  • Safari: not supported.

Source

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;
  }
}
Imagem de um carrossel com indicadores de pontos na parte de baixo
Captura de tela do marcador de rolagem básico na demonstração anterior.

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

  • Chrome: 133.
  • Edge: 133.
  • Firefox: not supported.
  • Safari: not supported.

popover=autopopover=manualpopover=hint
Dispensar leve (clicando fora ou usando a tecla esc)SimNãoSim
Fecha outros elementos popover=auto quando abertoSimNãoNão
Fecha outros elementos popover=hint quando abertoSimNãoSim
Fecha outros elementos popover=manual quando abertoNãoNãoNão
É possível abrir e fechar o popover com JS (showPopover() ou hidePopover())SimSimSim
Gerenciamento de foco padrão para a próxima parada de tabulaçãoSimSimSim
Pode ocultar ou alternar com popovertargetactionSimSimSim
Pode ser aberto no elemento pai popover para manter o elemento pai abertoSimSimSim

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: