As novidades sobre CSS e interface da Web: recapitulação do I/O 2024

A plataforma da Web está repleta de inovação, com recursos de CSS e interface da Web na vanguarda dessa evolução. Estamos vivendo uma era de ouro para a interface do usuário da Web, com novos recursos de CSS chegando aos navegadores em um ritmo inédito, abrindo um mundo de possibilidades para criar experiências da Web bonitas e envolventes. Nesta postagem do blog, vamos analisar o estado atual do CSS, explorando alguns dos novos recursos mais revolucionários que estão redefinindo a maneira como criamos aplicativos da Web, apresentados ao vivo no Google I/O 2024.

Novas experiências interativas

Uma experiência na Web é fundamentalmente uma troca entre você e seus usuários. Por isso, é tão importante investir em interações de qualidade. Estamos trabalhando em algumas melhorias muito importantes que desbloqueiam recursos inéditos na Web para navegar em páginas da Web e entre elas.

Animações de rolagem

Browser Support

  • Chrome: 115.
  • Edge: 115.
  • Firefox: behind a flag.
  • Safari: 26.

Source

Como o nome sugere, a API de animações de rolagem permite criar animações dinâmicas com base na rolagem sem depender de observadores de rolagem ou outros scripts pesados.

Criar animações de rolagem

Assim como as animações baseadas em tempo funcionam na plataforma, agora você pode usar o progresso de rolagem de um scroller para iniciar, pausar e reverter uma animação. Assim, conforme você rola para frente, o progresso da animação aparece, e quando você rola para trás, ele vai para o outro lado. Isso permite criar recursos visuais parciais ou de página inteira com elementos animados dentro da janela de visualização, também conhecida como scrollytelling, para um impacto visual dinâmico.

As animações baseadas em rolagem podem ser usadas para destacar conteúdo importante, guiar os usuários por uma história ou simplesmente adicionar um toque dinâmico às suas páginas da Web.

Elemento visual de animação controlada por rolagem

Demonstração ao vivo

@keyframes appear {
  from {
    opacity: 0;
    scale: 0.8;
  }
  to {
    opacity: 1;
    scale: 1;
  }
}

img {
  animation: appear linear;
  animation-timeline: view();
  animation-range: entry 25% cover 50%;
}

O código anterior define uma animação simples que aparece na janela de visualização mudando a opacidade e a escala de uma imagem. A animação é impulsionada pela posição de rolagem. Para criar esse efeito, primeiro configure a animação CSS e, em seguida, defina o animation-timeline. Nesse caso, a função view() com os valores padrão rastreia a imagem em relação à porta de rolagem (que, neste caso, também é a janela de visualização).

É importante ter em mente a compatibilidade com navegadores e as preferências dos usuários, principalmente para necessidades de acessibilidade. Portanto, use a regra @supports para verificar se o navegador é compatível com animações controladas por rolagem e envolva sua animação controlada por rolagem em uma consulta de preferência do usuário, como @media (prefers-reduced-motion: no-preference), para respeitar as preferências de movimento dos usuários. Depois de fazer essas verificações, você sabe que seus estilos vão funcionar e que a animação não é problemática para o usuário.

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* Apply scroll-driven animations here */
  }
}

As animações baseadas em rolagem podem significar experiências de scrollytelling em página inteira, mas também animações mais sutis, como uma barra de cabeçalho minimizando e mostrando uma sombra enquanto você rola um web app.

Elemento visual de animação controlada por rolagem

Demonstração ao vivo

@keyframes shrink-name {
  from {
    font-size: 2em;
  }
  to {
    font-size: 1.5em;
  }
}

@keyframes add-shadow {
  from {
    box-shadow: none;
  }
  to {
    box-shadow: 0 4px 2px -2px gray;
  }
}

header {
  animation: add-shadow linear both;
}

h2 {
  animation: shrink-name linear both;
}

header, h2 {
  animation-timeline: scroll();
  animation-range: 0 150px;
}

Esta demonstração usa algumas animações de frames-chave diferentes (cabeçalho, texto, barra de navegação e plano de fundo) e aplica a animação controlada por rolagem respectiva a cada uma delas. Embora cada uma tenha um estilo de animação diferente, todas têm a mesma linha do tempo de animação, o scroller mais próximo e o mesmo intervalo de animação, do topo da página até 150 pixels.

Benefícios de desempenho das animações de rolagem

Essa API integrada reduz uma carga de código que você precisaria manter, seja um script personalizado que você escreveu ou a inclusão de uma dependência adicional de terceiros. Também não é mais necessário enviar vários observadores de rolagem, o que significa benefícios de desempenho bastante significativos. Isso acontece porque as animações baseadas em rolagem funcionam na linha de execução principal ao animar propriedades que podem ser animadas no compositor, como transformações e opacidade, seja usando a nova API diretamente em CSS ou os hooks JavaScript.

A Tokopedia usou recentemente animações controladas por rolagem para fazer a barra de navegação de produtos aparecer conforme você rola a tela. O uso dessa API trouxe benefícios significativos para o gerenciamento de código e o desempenho.

As animações baseadas em rolagem impulsionam essa barra de navegação de produtos na Tokopedia enquanto você rola para baixo.

"Conseguimos reduzir até 80% das nossas linhas de código em comparação com o uso de eventos de rolagem JS convencionais e observamos que o uso médio da CPU caiu de 50% para 2% durante a rolagem. - Andy Wihalim, engenheiro de software sênior, Tokopedia"

O futuro dos efeitos de rolagem

Sabemos que esses efeitos vão continuar tornando a Web um lugar mais interessante, e já estamos pensando no que pode vir a seguir. Isso inclui a capacidade de não apenas usar novas linhas do tempo de animação, mas também usar um ponto de rolagem para acionar o início de uma animação, chamadas de animações acionadas por rolagem.

E ainda mais recursos de rolagem serão lançados para navegadores no futuro. A demonstração a seguir mostra uma combinação desses recursos futuros. Ele usa CSS scroll-start-target para definir a data e a hora iniciais nos seletores e o evento JavaScript scrollsnapchange para atualizar a data do cabeçalho, facilitando a sincronização dos dados com o evento ajustado.

Confira uma demonstração ao vivo no Codepen

Você também pode usar isso para atualizar um seletor em tempo real com o evento scrollsnapchanging do JavaScript.

Esses recursos específicos estão atualmente apenas no Canary por trás de uma flag. No entanto, eles desbloqueiam recursos que antes eram impossíveis ou muito difíceis de criar na plataforma e destacam o futuro das possibilidades de interações baseadas em rolagem.

Para saber mais sobre como começar a usar animações baseadas em rolagem, nossa equipe acabou de lançar uma nova série de vídeos no canal do YouTube Chrome for Developers. Aqui, você vai aprender o básico sobre animações controladas por rolagem com Bramus Van Damme, incluindo como o recurso funciona, vocabulário, várias maneiras de criar efeitos e como combinar efeitos para criar experiências avançadas. É uma ótima série de vídeos para conferir.

Ver transições

Acabamos de falar sobre um novo recurso incrível que anima dentro das páginas da Web. Mas também há um novo recurso incrível chamado transições de visualização para animar entre visualizações de página e criar uma experiência do usuário integrada. As transições de visualização introduzem um novo nível de fluidez na Web, permitindo criar transições perfeitas entre diferentes visualizações em uma única página ou até mesmo em páginas diferentes.

Browser Support

  • Chrome: 111.
  • Edge: 111.
  • Firefox: 144.
  • Safari: 18.

Source

O Airbnb é uma das empresas que já estão testando a integração de transições de visualização na interface para uma experiência de navegação na Web suave e perfeita. Isso inclui a barra lateral do editor de anúncios, a edição de fotos e a adição de comodidades, tudo em um fluxo contínuo do usuário.

Uma transição de visualização no mesmo documento, como visto no Airbnb.
O portfólio de Maxwell Barvian, mostrando transições de visualização entre visualizações.

Embora esses efeitos de tela inteira sejam bonitos e perfeitos, você também pode criar microinterações, como neste exemplo em que a visualização em lista é atualizada na interação do usuário. Esse efeito pode ser alcançado sem esforço com as transições de visualização.

Para ativar rapidamente as transições de visualização no seu aplicativo de página única, basta envolver uma interação usando document.startViewTransition e garantir que cada elemento em transição tenha um view-transition-name, inline ou dinamicamente usando JavaScript ao criar nós DOM.

Demonstração visual

Demonstração ao vivo

document.querySelectorAll('.delete-btn').forEach(btn => {
  btn.addEventListener('click', () => {
    document.startViewTransition(() => {
      btn.closest('.card').remove();
    });
  })
});
/* Styles for the transition animation */
::view-transition-old(.card):only-child {
  animation: fade-out ease-out 0.5s;
}

Ver classes de transição

Os nomes de transição de visualização podem ser usados para aplicar animações personalizadas à transição de visualização, mas isso pode ficar complicado com muitos elementos em transição. A primeira atualização das transições de visualização deste ano simplifica esse problema e apresenta a capacidade de criar classes de transição de visualização que podem ser aplicadas a animações personalizadas.

Browser Support

  • Chrome: 125.
  • Edge: 125.
  • Firefox: 144.
  • Safari: 18.2.

Source

Ver tipos de transição

Outra grande melhoria para as transições de visualização é o suporte a tipos de transição de visualização. Os tipos de transição de visualização são úteis quando você quer um tipo diferente de transição de visualização visual ao animar para e de visualizações de página.

Browser Support

  • Chrome: 125.
  • Edge: 125.
  • Firefox: 144.
  • Safari: 18.

Source

Por exemplo, talvez você queira que uma página inicial seja animada para uma página de blog de uma maneira diferente da animação da página de blog de volta para a página inicial. Ou talvez você queira que as páginas troquem de lugar de maneiras diferentes, como neste exemplo, indo da esquerda para a direita e vice-versa. Antes, isso era complicado. Era possível adicionar classes ao DOM para aplicar estilos e depois remover as classes. Os tipos de transição de visualização permitem que o navegador limpe as transições antigas em vez de exigir que você faça isso manualmente antes de iniciar novas, fazendo esse trabalho para você.

Gravação da demonstração de paginação. Os tipos determinam qual animação usar. Os estilos são separados na folha de estilo graças aos tipos de transição ativos.

É possível configurar tipos na função document.startViewTransition, que agora aceita um objeto. update é a função de callback que atualiza o DOM, e types é uma matriz com os tipos.

document.startViewTransition({
  update: myUpdate,
  types: ['slide', 'forwards']
})

Transições de visualização de várias páginas

O que torna a Web poderosa é a expansão dela. Muitos aplicativos não são apenas uma página única, mas um conjunto robusto com várias páginas. Por isso, temos o prazer de anunciar que estamos lançando o suporte a transições de visualização entre documentos para aplicativos de várias páginas no Chromium 126.

Browser Support

  • Chrome: 126.
  • Edge: 126.
  • Firefox: not supported.
  • Safari: 18.2.

Source

Esse novo conjunto de recursos entre documentos inclui experiências da Web que ficam na mesma origem, como navegar de web.dev para web.dev/blog. No entanto, não inclui a navegação entre origens, como de web.dev para blog.web.dev ou para outro domínio, como google.com.

Uma das principais diferenças das transições de visualização no mesmo documento é que não é necessário incluir a transição em document.startViewTransition(). Em vez disso, ative as duas páginas envolvidas na transição de visualização usando a regra at @view-transition do CSS.

@view-transition {
  navigation: auto;
}

Para um efeito mais personalizado, você pode usar JavaScript com os novos listeners de eventos pageswap ou pagereveal, que dão acesso ao objeto de transição de visualização.

Com o pageswap, você pode fazer algumas mudanças de última hora na página de saída antes que os snapshots antigos sejam feitos. Já com o pagereveal, é possível personalizar a nova página antes que ela comece a ser renderizada após a inicialização.

window.addEventListener('pageswap', async (e) => {
    // ...
});

window.addEventListener('pagereveal', async (e) => {
    // ...
});
Mostrando transições de visualização em um app de várias páginas. Consulte o link de demonstração.

No futuro, planejamos expandir as transições de visualização, incluindo:

  • Transições com escopo: permitem limitar uma transição a uma subárvore DOM, possibilitando que o restante da página continue interativo e oferecendo suporte a várias transições de visualização em execução ao mesmo tempo.
  • Transições de visualização orientadas por gestos: use gestos de arrastar ou deslizar para acionar uma transição de visualização entre documentos e ter experiências mais nativas na Web.
  • Correspondência de navegação em CSS: personalize sua transição de visualização entre documentos diretamente no CSS como alternativa ao uso de eventos pageswap e pagereveal em JavaScript. Para saber mais sobre transições de visualização em aplicativos de várias páginas, incluindo como configurá-las da maneira mais eficiente com pré-renderização, confira a seguinte palestra de Bramus Van Damme:

Componentes de interface ativados pelo mecanismo: simplificando interações complexas

Criar aplicativos da Web complexos não é fácil, mas o CSS e o HTML estão evoluindo para tornar esse processo muito mais gerenciável. Novos recursos e melhorias estão simplificando a criação de componentes de interface, permitindo que você se concentre na criação de ótimas experiências. Isso é feito por um esforço colaborativo que envolve vários órgãos de padrões e grupos da comunidade importantes, incluindo o grupo de trabalho do CSS, o grupo da comunidade Open UI e o WHATWG (grupo de trabalho da tecnologia de aplicativos de hipertexto da Web).

Um grande problema para os desenvolvedores é um pedido aparentemente simples: a capacidade de estilizar menus suspensos (o elemento de seleção). Embora pareça simples, esse é um problema complexo que afeta muitas partes da plataforma, desde layout e renderização até rolagem e interação, passando por estilização do user agent e propriedades CSS, e até mesmo mudanças no próprio HTML.

Selecionar com lista de opções que têm opções dentro, botão de acionamento, seta indicadora e opção selecionada.
Como dividir os elementos de uma seleção

Um menu suspenso consiste em muitas partes e inclui vários estados que precisam ser considerados, como:

  • Vinculações de teclado (para entrar/sair da interação)
  • Clique fora para dispensar
  • Gerenciamento ativo de popovers (fecha outros popovers quando um é aberto)
  • Gerenciamento de foco na guia
  • Visualizar o valor da opção selecionada
  • Estilo de interação com seta
  • Gerenciamento de estado (aberto/fechado)

Atualmente, é difícil gerenciar todo esse estado por conta própria, mas a plataforma também não facilita. Para corrigir isso, dividimos essas partes e estamos lançando alguns recursos primitivos que vão permitir estilizar menus suspensos, mas também fazer muito mais.

A API Popover

Primeiro, lançamos um atributo global chamado popover, que, há algumas semanas, atingiu o status de recém-disponível da linha de base.

Browser Support

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

Source

Os elementos de popover ficam ocultos com display: none até serem abertos com um invocador, como um botão ou JavaScript. Para criar um popover básico, defina o atributo popover no elemento e vincule o ID dele a um botão usando popovertarget. Agora, o botão é o invocador.

Demonstração visual

Demonstração ao vivo

<button popovertarget="my-popover">Open Popover</button>

<div id="my-popover" popover>
  <p>I am a popover with more information.</p>
</div>

Com o atributo popover ativado, o navegador processa muitos comportamentos importantes sem scripts adicionais, incluindo:

  • Promoção para a camada superior: Uma camada separada acima do restante da página, para que você não precise mexer com z-index.
  • Funcionalidade de dispensa leve: Clicar fora da área do popover fecha o popover e retorna o foco.
  • Gerenciamento de foco da guia padrão: Ao abrir o popover, a próxima parada de tabulação fica dentro dele.
  • Vinculações de teclado integradas: Ao pressionar a tecla esc ou alternar duas vezes, o popover será fechado e o foco será retornado.
  • Vinculações de componentes padrão. : o navegador conecta semanticamente um popover ao gatilho dele.
Tela inicial do GitHub
Menu na página inicial do GitHub.

Talvez você já esteja usando essa API sem perceber. O GitHub implementou o popover no menu "novo" da página inicial e na visão geral da revisão de solicitação de envio. Eles aprimoraram progressivamente esse recurso usando o polyfill de popover, criado pela Oddbird com o apoio significativo de Keith Cirkel, do GitHub, para oferecer suporte a navegadores mais antigos.

"Conseguimos descontinuar literalmente milhares de linhas de código ao migrar para o popover. O popover nos ajuda eliminando a necessidade de lutar contra números mágicos de z-index... ter a relação correta da árvore de acessibilidade estabelecida com o comportamento declarativo do botão e comportamentos de foco integrados facilita significativamente a implementação correta de padrões pelo nosso sistema de design. Keith Cirkel, engenheiro de software, GitHub"

Animação de efeitos de entrada e saída

Quando você tem popovers, provavelmente vai querer adicionar alguma interação. Há quatro novos recursos de interação lançados no ano passado para oferecer suporte a popovers animados. São eles:

A capacidade de animar display e content-visibility em uma linha do tempo de frames-chave.

A propriedade transition-behavior com a palavra-chave allow-discrete para ativar transições de propriedades discretas, como display.

Browser Support

  • Chrome: 117.
  • Edge: 117.
  • Firefox: 129.
  • Safari: 17.4.

Source

A regra @starting-style para animar efeitos de entrada de display: none para a camada superior.

Browser Support

  • Chrome: 117.
  • Edge: 117.
  • Firefox: 129.
  • Safari: 17.5.

Source

A propriedade de sobreposição para controlar o comportamento da camada superior durante uma animação.

Browser Support

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

Source

Essas propriedades funcionam para qualquer elemento que você esteja animando na camada superior, seja um popover ou uma caixa de diálogo. Juntando tudo, fica assim para uma caixa de diálogo com um plano de fundo:

Demonstração visual

Demonstração ao vivo

dialog, ::backdrop{
  opacity: 0;
  transition: opacity 1s, display 1s allow-discrete, overlay 1s allow-discrete;
}

[open], [open]::backdrop {
  opacity: 1;
}

@starting-style {
  [open], [open]::backdrop {
    opacity: 0;
  }
}

Primeiro, configure o @starting-style para que o navegador saiba quais estilos animar esse elemento no DOM. Isso é feito para a caixa de diálogo e o plano de fundo. Em seguida, estilize o estado aberto da caixa de diálogo e do plano de fundo. Para uma caixa de diálogo, isso usa o atributo open e, para um popover, o pseudoelemento ::popover-open. Por fim, anime opacity, display e overlay usando a palavra-chave allow-discrete para ativar o modo de animação em que propriedades discretas podem fazer a transição.

Posicionamento da âncora

O popover foi apenas o começo da história. Uma atualização muito interessante é que o suporte ao posicionamento de âncora agora está disponível no Chrome 125.

Browser Support

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

Source

Usando o posicionamento de âncora, com apenas algumas linhas de código, o navegador pode processar a lógica para vincular um elemento posicionado a um ou mais elementos de âncora. No exemplo a seguir, uma dica simples é ancorada em cada botão, posicionada na parte de baixo do centro.

Demonstração visual

Demonstração ao vivo

Configure uma relação de posicionamento de âncora em CSS usando a propriedade anchor-name no elemento de ancoragem (neste caso, o botão) e a propriedade position-anchor no elemento posicionado (neste caso, a dica). Em seguida, aplique o posicionamento absoluto ou fixo em relação à âncora usando a função anchor(). O código a seguir posiciona a parte de cima da dica na parte de baixo do botão.

.anchor {
  anchor-name: --my-anchor;
}

.positioned {
  position: absolute;
  position-anchor: --my-anchor;
}

Como alternativa, use o anchor-name diretamente na função de âncora e pule a propriedade position-anchor. Isso pode ser útil ao ancorar em vários elementos.

.anchor {
  anchor-name: --my-anchor;
}

.positioned {
  position: absolute;
  top: anchor(--my-anchor bottom);
}

Por fim, use a nova palavra-chave anchor-center para as propriedades justify e align e centralize o elemento posicionado no âncora.

.anchor {
  anchor-name: --my-anchor;
}

.positioned {
  position: absolute;
  top: anchor(--my-anchor bottom);
  justify-self: anchor-center;
}

Embora seja muito conveniente usar o posicionamento de âncora com o popover, ele não é um requisito para usar o posicionamento de âncora. O posicionamento de âncora pode ser usado com dois ou mais elementos para criar uma relação visual. Na verdade, a demonstração a seguir, inspirada em um artigo de Roman Komarov, mostra um estilo de sublinhado ancorado a itens de lista quando você passa o cursor ou pressiona a tecla Tab sobre eles.

Demonstração visual

Demonstração ao vivo

Este exemplo usa a função de fixação para definir a posição de fixação usando as propriedades físicas de left, right e bottom. Quando você passa o cursor sobre um dos links, a âncora de destino muda, e o navegador move o destino para aplicar o posicionamento, também animando a cor ao mesmo tempo para criar um efeito interessante.

ul::before {
  content: "";
  position: absolute;
  left:   anchor(var(--target) left);
  right:  anchor(var(--target) right);
  bottom: anchor(var(--target) bottom);
  ...
}

li:nth-child(1) { --anchor: --item-1 }
ul:has(:nth-child(1) a:is(:hover, :focus-visible)) {
  --target: --item-1;
  --color: red;
}

Posicionamento de inset-area

Além do posicionamento absoluto direcional padrão que você provavelmente já usou, há um novo mecanismo de layout incluído que chegou como parte da API de posicionamento de âncora chamada área de encarte. A área de encarte facilita a colocação de elementos posicionados em relação às respectivas âncoras e funciona em uma grade de nove células com o elemento de ancoragem no centro. Por exemplo, inset-area: top coloca o elemento posicionado na parte de cima, e inset-area: bottom coloca o elemento posicionado na parte de baixo.

Uma versão simplificada da primeira demonstração de âncora fica assim com inset-area:

.anchor {
  anchor-name: --my-anchor;
}

.positioned {
  position: absolute;
  position-anchor: --my-anchor;
  inset-area: bottom;
}

Você pode combinar esses valores posicionais com palavras-chave de extensão para começar na posição central e se estender para a esquerda, para a direita ou para todos os lados, ocupando o conjunto completo de colunas ou linhas disponíveis. Você também pode usar propriedades lógicas. Para facilitar a visualização e o uso desse mecanismo de layout, confira esta ferramenta no Chrome 125 ou mais recente:

Como esses elementos estão ancorados, o elemento posicionado se move dinamicamente pela página à medida que a âncora se move. Nesse caso, temos elementos de card estilizados com consultas de contêiner, que são redimensionados com base no tamanho intrínseco (algo que não é possível fazer com consultas de mídia), e o menu ancorado vai mudar com o novo layout à medida que a interface do card muda.

Demonstração visual

Demonstração ao vivo

Posições de âncora dinâmicas com position-try-options

É muito mais fácil criar menus e navegação por submenu com uma combinação de posicionamento de popover e âncora. Além disso, quando você atinge a borda de uma janela de visualização com o elemento ancorado, é possível deixar o navegador processar a mudança de posição para você. Isso pode ser feito de algumas maneiras. A primeira é criar suas próprias regras de posicionamento. Nesse caso, o submenu é posicionado inicialmente à direita do botão "vitrine". Mas você pode criar um bloco @position-try para quando não houver espaço suficiente à direita do menu, atribuindo a ele um identificador personalizado de --bottom. Em seguida, conecte esse bloco @position-try à âncora usando position-try-options.

Agora, o navegador vai alternar entre esses estados fixos, tentando primeiro a posição correta e depois mudando para a parte de baixo. Isso pode ser feito com uma transição suave.

Demonstração visual

Demonstração ao vivo

#submenu {
  position-anchor: --submenu;
  top: anchor(top);
  left: anchor(right);
  margin-left: var(--padding);

  position-try-options: --bottom;

  transition: top 0.25s, left 0.25s;
  width: max-content;
}

@position-try --bottom {
  top: anchor(left);
  left: anchor(bottom);
  margin-left: var(--padding);
}

Além da lógica de posicionamento explícito, há algumas palavras-chave fornecidas pelo navegador se você quiser interações básicas, como inverter a âncora no bloco ou direções inline.

position-try-options: flip-block, flip-inline;

Para uma experiência de inversão simples, aproveite esses valores de palavra-chave de inversão e pule a escrita de uma definição de position-try. Agora você pode ter um elemento ancorado totalmente funcional e responsivo à localização com apenas algumas linhas de CSS.

Demonstração visual

Demonstração ao vivo

.tooltip {
  inset-area: top;
  position-try-options: flip-block;
}

Saiba mais sobre como usar o posicionamento de âncora.

O futuro da interface em camadas

Vemos experiências vinculadas em todos os lugares, e o conjunto de recursos mostrado nesta postagem é um excelente começo para liberar a criatividade e ter mais controle sobre elementos posicionados por âncora e interfaces em camadas. Mas este é apenas o começo. Por exemplo, no momento, popover só funciona com botões como elemento de invocação ou com JavaScript. Para algo como prévias no estilo Wikipédia, um padrão visto em toda a plataforma da Web, é necessário poder interagir e também acionar um popover de um link e do usuário mostrando interesse sem necessariamente clicar, como um foco de passar o cursor ou de guia.

Como próxima etapa da API popover, estamos trabalhando em interesttarget para resolver essas necessidades e facilitar a recriação dessas experiências com os hooks de acessibilidade adequados integrados. Esse é um problema de acessibilidade difícil de resolver, com muitas questões em aberto sobre comportamentos ideais. No entanto, resolver e normalizar essa funcionalidade em nível de plataforma deve melhorar essas experiências para todos.

<a interesttarget="my-tooltip">Hover/Focus to show the tooltip</a>

<span popover=hint id="my-toolip">This is the tooltip</span>

Além disso, há outro invocador geral voltado para o futuro (invoketarget) disponível para teste no Canary graças ao trabalho de dois desenvolvedores terceirizados, Keith Cirkel e Luke Warlow. O invoketarget oferece suporte à experiência declarativa do desenvolvedor que o popovertarget fornece popovers, normalizados para todos os elementos interativos, incluindo <dialog>, <details>, <video>, <input type="file"> e muito mais.

<button invoketarget="my-dialog">
  Open Dialog
</button>

<dialog id="my-dialog">
  Hello world!
</dialog>

Sabemos que ainda há casos de uso que não são cobertos por essa API. Por exemplo, estilizar a seta que conecta um elemento fixado ao âncora, principalmente quando a posição do elemento fixado muda, e permitir que um elemento "deslize" e permaneça na janela de visualização em vez de se ajustar a outra posição definida quando atinge a caixa delimitadora. Estamos muito felizes em lançar essa API poderosa, mas também queremos expandir ainda mais os recursos dela no futuro.

Seleção estilizada

Usando popover e anchor juntos, a equipe tem avançado para finalmente ativar um menu suspenso de seleção personalizável. A boa notícia é que houve muito progresso. A má notícia é que essa API ainda está em um estado experimental. No entanto, estou animado para compartilhar algumas demonstrações ao vivo e atualizações sobre nosso progresso e, espero, receber seu feedback. Primeiro, houve progresso em como ativar a nova experiência de seleção personalizável para os usuários. A maneira atual de fazer isso é usar uma propriedade de aparência em CSS, definida como appearance: base-select. Depois que a aparência for definida, você vai ativar uma nova experiência de seleção personalizável.

select {
  appearance: base-select;
}

Além de appearance: base-select, há algumas novas atualizações de HTML. Isso inclui a capacidade de incluir suas opções em um datalist para personalização e adicionar conteúdo não interativo arbitrário, como imagens, às opções. Você também terá acesso a um novo elemento, <selectedoption>, que vai refletir o conteúdo das opções em si, e que você poderá personalizar de acordo com suas necessidades. Esse elemento é muito útil.

Demonstração visual

flag demo

Demonstração ao vivo

<select>
  <button type=popover>
    <selectedoption></selectedoption>
  </button>
  <datalist>
    <option value="" hidden>
      <p>Select a country</p>
    </option>
    <option value="andorra">
      <img src="Flag_of_Andorra.svg" />
      <p>Andorra</p>
    </option>
    <option value="bolivia">
      <img src="Flag_of_Bolivia.svg" />
      <p>Bolivia</p>
    </option>
...
  </datalist>
</select>

O código a seguir demonstra a personalização de <selectedoption> na interface do Gmail, em que um ícone visual representa o tipo de resposta selecionada para economizar espaço. Você pode usar estilos de exibição básicos em selectedoption para diferenciar o estilo da opção do estilo da prévia. Nesse caso, o texto mostrado na opção pode ser ocultado visualmente no selectedoption.

Demonstração visual

demonstração do Gmail

Demonstração ao vivo

selectedoption .text {
  display: none;
}

Uma das maiores vantagens de reutilizar o elemento <select> para essa API é a compatibilidade com versões anteriores. Nessa seleção de país, você pode ver uma interface personalizada com imagens de bandeiras nas opções para facilitar a análise do conteúdo pelo usuário. Como os navegadores não compatíveis ignoram as linhas que não entendem, como o botão personalizado, a lista de dados, a opção selecionada e as imagens nas opções, o substituto será semelhante à interface de seleção padrão atual.

Navegador incompatível recebe a experiência de seleção atual.
Visualização do navegador compatível à esquerda e fallback do navegador incompatível à direita.

Com seleções personalizáveis, as possibilidades são infinitas. Eu gosto muito desse seletor de país no estilo Airbnb porque ele tem um estilo inteligente para design responsivo. Você pode fazer isso e muito mais com o seletor estilizado, o que o torna uma adição muito necessária à plataforma da Web.

Demonstração visual

Demonstração ao vivo

Acordeão exclusivo

Resolver o estilo de seleção (e todas as partes relacionadas) não é o único componente de UI em que a equipe do Chrome tem se concentrado. A primeira atualização de componente adicional é a capacidade de criar acordeões exclusivos, em que apenas um dos itens pode ser aberto por vez.

Browser Support

  • Chrome: 120.
  • Edge: 120.
  • Firefox: 130.
  • Safari: 17.2.

Para ativar isso, aplique o mesmo valor de nome a vários elementos de detalhes, criando um grupo conectado de detalhes, assim como um grupo de botões de opção.

Demonstração exclusiva de acordeão
<details name="learn-css" open>
  <summary>Welcome to Learn CSS!</summary>
</details>

<details name="learn-css">
  <summary>Box Model</summary>
  <p>...</p>
</details>

<details name="learn-css">
  <summary>Selectors</summary>
  <p>...</p>
</details>

:user-valid e :user-invalid

Outra melhoria no componente da interface são as pseudoclasses :user-valid e :user-invalid. Estáveis em todos os navegadores recentemente, as pseudoclasses :user-valid e :user-invalid se comportam de maneira semelhante às pseudoclasses :valid e :invalid, mas correspondem a um controle de formulário somente depois que um usuário interage significativamente com a entrada. Isso significa que é necessário muito menos código para determinar se um valor de formulário foi usado ou se tornou "sujo", o que pode ser muito útil para fornecer feedback ao usuário e reduz muito o script que seria necessário para fazer isso no passado.

Browser Support

  • Chrome: 119.
  • Edge: 119.
  • Firefox: 88.
  • Safari: 16.5.

Source

Screencast de demonstração

Demonstração ao vivo

input:user-valid,
select:user-valid,
textarea:user-valid {
    --state-color: green;
    --bg: linear-gradient(...);
}

input:user-invalid,
select:user-invalid,
textarea:user-invalid {
    --state-color: red;
    --bg: linear-gradient(...);
}

Saiba como usar os pseudoelementos de validação de formulário user-*.

field-sizing: content

Outra atualização útil de componente que chegou recentemente é o field-sizing: content, que pode ser aplicado a controles de formulário, como entradas e textareas. Isso permite que o tamanho da entrada aumente ou diminua dependendo do conteúdo. O field-sizing: content é muito útil para áreas de texto, já que você não precisa mais rolar para cima para ver o que escreveu nas partes anteriores do comando em uma caixa de entrada muito pequena.

Browser Support

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

Source

Screencast de demonstração

Demonstração ao vivo

textarea, select, input {
  field-sizing: content;
}

Saiba mais sobre o dimensionamento de campos.

<hr> em <select>

A capacidade de ativar o <hr> ou o elemento de regra horizontal em seleções é outro recurso de componente pequeno, mas útil. Embora isso não tenha muito uso semântico, ajuda a separar bem o conteúdo em uma lista de seleção, especialmente o conteúdo que você não quer agrupar com um optgroup, como um valor de marcador de posição.

Selecionar captura de tela

Captura de tela de hr em select com um tema claro e escuro no Chrome

Selecione "Demonstração ao vivo"

<select name="majors" id="major-select">
  <option value="">Select a major</option>
  <hr>
  <optgroup label="School of Fine Arts">
    <option value="arthist">
Art History
  </option>
  <option value="finearts">
    Fine Arts
  </option>
...
</select>

Saiba mais sobre como usar hr em select.

Melhorias na qualidade de vida

Estamos sempre iterando, e não é apenas para interações e componentes. Há muitas outras atualizações de qualidade de vida que foram lançadas no ano passado.

Aninhamento com lookahead

O aninhamento nativo de CSS chegou a todos os navegadores no ano passado e, desde então, foi aprimorado para oferecer suporte ao lookahead. Isso significa que o & antes dos nomes de elementos não é mais um requisito. Isso torna o aninhamento muito mais ergonômico e semelhante ao que eu estava acostumado no passado.

Browser Support

  • Chrome: 120.
  • Edge: 120.
  • Firefox: 117.
  • Safari: 17.2.

Source

Uma das minhas coisas favoritas sobre o aninhamento de CSS é que ele permite bloquear visualmente componentes e incluir estados e modificadores nesses componentes, como consultas de contêiner e de mídia. Antes, eu agrupava todas essas consultas na parte de baixo do arquivo para fins de especificidade. Agora, você pode escrever esses comentários de uma forma que faça sentido, ao lado do restante do código.

.card {
  /* card base styles */

  h2 {
    /* child element style */
  }

  &.highlight {
    /* modifier style */
  }

  &:hover, &:focus {
    /* state styles */
  }

  @container (width >= 300px) {
    /* container query styles */
  }
}

Alinhamento de conteúdo para layout de bloco

Outra mudança muito interessante é a capacidade de usar mecanismos de centralização, como align-content, no layout de bloco. Isso significa que agora você pode fazer coisas como centralização vertical em uma div sem precisar aplicar flex ou layout de grade e sem efeitos colaterais, como impedir o recolhimento de margens, que talvez você não queira desses algoritmos de layout.

Browser Support

  • Chrome: 123.
  • Edge: 123.
  • Firefox: 125.
  • Safari: 17.4.

Captura de tela

Demonstração ao vivo

div {
  align-content: center;
}

Quebra de texto: balance e pretty

Falando em layout, o layout de texto recebeu uma boa melhoria com a adição de text-wrap: balance e pretty. text-wrap: balance é usado para um bloco de texto mais uniforme, enquanto text-wrap: pretty se concentra em reduzir palavras isoladas na última linha do texto.

Screencast de demonstração

Demonstração ao vivo

Na demonstração a seguir, arraste o controle deslizante para comparar os efeitos de balance e pretty em um cabeçalho e um parágrafo. Tente traduzir a demonstração para outro idioma.
h1 {
  text-wrap: balance;
}

Saiba mais sobre text-wrap: balance.

Atualizações de tipografia internacional

Atualizações de layout tipográfico para recursos de texto CJK receberam muitas atualizações interessantes no ano passado, como o recurso word-break: auto-phrase, que quebra a linha no limite natural da frase.

Browser Support

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

word-break: auto-phrase quebra a linha no limite natural da frase.
Comparação entre word-break: normal e word-break: auto-phrase

E text-spacing-trim, que aplica o kerning entre caracteres de pontuação para melhorar a legibilidade da tipografia chinesa, japonesa e coreana e gerar resultados mais agradáveis visualmente.

Browser Support

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

Source

A metade direita do ponto final CJK é removida com text-spacing-trim.
Quando caracteres de pontuação aparecem em sequência, a metade direita do ponto final CJK precisa ser removida.

Sintaxe de cor relativa

No mundo da aplicação de temas de cores, tivemos uma grande atualização com a sintaxe de cores relativas.

Neste exemplo, as cores usam temas baseados em Oklch. À medida que o valor de matiz é ajustado com base no controle deslizante, todo o tema muda. Isso pode ser feito com a sintaxe de cores relativas. O plano de fundo usa a cor primária, com base na tonalidade, e ajusta os canais de luminosidade, croma e tonalidade para ajustar o valor. --i é o índice irmão na lista para a gradação de valores, mostrando como combinar etapas com propriedades personalizadas e sintaxe de cores relativas para criar temas.

Screencast de demonstração

Demonstração ao vivo

Na demonstração a seguir, arraste o controle deslizante para comparar os efeitos de balance e pretty em um cabeçalho e um parágrafo. Tente traduzir a demonstração para outro idioma.
:root {
  --hue: 230;
  --primary: oklch(70% .2 var(--hue));
}

li {
  --_bg: oklch(from var(--primary)
    calc(l - (var(--i) * .05))
    calc(c - (var(--i) * .01))
    calc(h - (var(--i) + 5)));
}

Função light-dark()

Junto com a função light-dark(), a criação de temas ficou muito mais dinâmica e simplificada.

Browser Support

  • Chrome: 123.
  • Edge: 123.
  • Firefox: 120.
  • Safari: 17.5.

Source

A função light-dark() é uma melhoria ergonômica que simplifica as opções de temas de cores para que você possa escrever estilos de tema de maneira mais concisa, conforme demonstrado neste diagrama visual de Adam Argyle. Antes, você precisava de dois blocos de código diferentes (seu tema padrão e uma consulta de preferência do usuário) para configurar as opções de tema. Agora, é possível escrever essas opções de estilo para temas claros e escuros na mesma linha de CSS usando a função light-dark().

Visualização de light-dark(). Consulte a demonstração para mais informações.
html {
  color-scheme: light dark;
}

button {
    background-color: light-dark(lightblue, darkblue);
}

Se o usuário tiver selecionado um tema claro, o botão terá um plano de fundo azul-claro. Se o usuário tiver selecionado um tema escuro, o botão terá um plano de fundo azul-escuro.

Seletor de :has()

E seria negligente falar sobre a interface moderna sem mencionar um dos destaques de interoperabilidade mais impactantes do ano passado, que é o seletor :has(), lançado em todos os navegadores em dezembro do ano passado. Essa API é uma inovação para escrever estilos lógicos.

Browser Support

  • Chrome: 105.
  • Edge: 105.
  • Firefox: 121.
  • Safari: 15.4.

Source

O seletor :has() permite verificar se um elemento filho tem filhos específicos ou se esses filhos estão em um estado específico e, essencialmente, também pode funcionar como um seletor pai.

Demonstração do uso de has() para estilizar blocos de comparação na Tokopedia.

O :has() já se mostrou particularmente útil para muitas empresas, incluindo a PolicyBazaar, que usa o :has() para estilizar blocos com base no conteúdo interno, como na seção de comparação, em que o estilo é ajustado se houver um plano para comparar no bloco ou se ele estiver vazio.

"Com o seletor :has(), eliminamos a validação baseada em JavaScript da seleção do usuário e a substituímos por uma solução em CSS que funciona perfeitamente para nós com a mesma experiência de antes."–Aman Soni, líder técnico, PolicyBazaar

Consultas em contêiner

Outra adição importante à Web, que agora está disponível e crescendo em uso, são as consultas de contêiner, que permitem consultar o tamanho intrínseco de um elemento pai para aplicar estilos. Isso é muito mais preciso do que as consultas de mídia, que consultam apenas o tamanho da janela de visualização.

Browser Support

  • Chrome: 105.
  • Edge: 105.
  • Firefox: 110.
  • Safari: 16.

Source

O Angular lançou recentemente um novo site de documentação em angular.dev usando consultas de contêiner para estilizar os blocos de cabeçalho com base no espaço disponível na página. Assim, mesmo que o layout mude de uma barra lateral de várias colunas para uma de coluna única, os blocos de cabeçalho podem se ajustar automaticamente.

Angular.dev mostrando consultas de contêiner nos cards do cabeçalho.

Sem consultas de contêiner, fazer algo assim era muito difícil e prejudicial à performance, exigindo observadores de redimensionamento e de elementos. Agora, é trivial estilizar um elemento com base no tamanho do elemento pai.

Screencast de demonstração

Demonstração ao vivo

Recriando a consulta de contêiner do card de cabeçalho do Angular.

@property

E, em breve, vamos lançar @property na Baseline. Esse é um recurso fundamental para dar significado semântico às propriedades personalizadas do CSS (também conhecidas como variáveis CSS) e permite vários novos recursos de interação. O @property também permite significado contextual, verificação de tipos, padrões e valores de substituição em CSS. Abrindo as portas para recursos ainda mais robustos, como consultas de estilo de intervalo. Esse é um recurso que nunca foi possível antes e agora oferece muito mais profundidade à linguagem do CSS.

Browser Support

  • Chrome: 85.
  • Edge: 85.
  • Firefox: 128.
  • Safari: 16.4.

Source

Screencast de demonstração

Demonstração ao vivo

@property --card-bg {
  syntax: "<color>";
  inherits: false;
  initial-value: #c0bae8;
}

Conclusão

Com todos esses novos recursos avançados de interface do usuário chegando aos navegadores, as possibilidades são infinitas. Novas experiências interativas com animações baseadas em rolagem e transições de visualização tornam a Web mais fluida e interativa de maneiras inéditas. Além disso, os componentes de interface de próxima geração facilitam a criação de componentes robustos e personalizados sem remover toda a experiência nativa. Por fim, as melhorias na qualidade de vida em arquitetura, layout, tipografia e design responsivo não apenas resolvem os pequenos grandes problemas, mas também oferecem aos desenvolvedores as ferramentas necessárias para criar interfaces complexas que funcionam em vários dispositivos, formatos e necessidades do usuário.

Com esses novos recursos, você poderá remover scripts de terceiros para recursos que exigem muito desempenho, como scrollytelling e elementos de tethering entre si com posicionamento de âncora, criar transições de página fluidas, estilizar menus suspensos e melhorar a estrutura geral do seu código de forma nativa.

Nunca houve um momento melhor para ser um desenvolvedor da Web. Não havia tanta energia e entusiasmo desde o anúncio do CSS3. Recursos que precisávamos, mas só sonhávamos em ter, estão finalmente se tornando realidade e fazendo parte da plataforma. É por causa da sua voz que conseguimos priorizar e finalmente dar vida a esses recursos. Estamos trabalhando para facilitar a realização das tarefas difíceis e tediosas de forma nativa. Assim, você pode passar mais tempo criando o que importa, como os recursos principais e os detalhes de design que diferenciam sua marca.

Para saber mais sobre esses novos recursos à medida que eles forem lançados, acompanhe developer.chrome.com e web.dev, onde nossa equipe compartilha as últimas notícias em tecnologias da Web. Teste animações controladas por rolagem, transições de visualização, posicionamento de âncora ou até mesmo a seleção estilizada e conte o que você achou. Estamos aqui para ouvir e ajudar.