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

A plataforma da Web está cheia de inovações, com recursos de CSS e interface da Web na vanguarda dessa evolução. Estamos vivendo uma era de ouro para a interface da Web, com novos recursos de CSS sendo lançados em navegadores a uma velocidade sem precedentes, abrindo um mundo de possibilidades para criar experiências da Web incríveis e envolventes. Esta postagem do blog vai se aprofundar no estado atual do CSS, explorando alguns dos novos recursos mais inovadores que estão redefinindo a forma como criamos aplicativos da Web, apresentados ao vivo no Google I/O 2024.

Novas experiências interativas

Uma experiência na Web é, basicamente, uma chamada e uma resposta entre você e seus usuários. É por isso que é tão importante investir em interações de qualidade. Estamos trabalhando em algumas melhorias muito grandes que liberam recursos que nunca tivemos antes na Web para navegar dentro e entre páginas da Web.

Animações de rolagem

Compatibilidade com navegadores

  • Chrome: 115.
  • Edge: 115.
  • Firefox: atrás de uma flag.
  • Safari: não é compatível.

Origem

Como o nome indica, a API de animações de rolagem permite criar animações dinâmicas baseadas em 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, a animação avança, e quando você rola para trás, ela vai para o outro lado. Isso permite criar recursos visuais parciais ou de página inteira com elementos animados dentro da viewport, também conhecidos como scrollytelling, para um impacto visual dinâmico.

As animações movidas por 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.

Visualização de animação com 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 viewport ao mudar 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 depois defina o animation-timeline. Nesse caso, a função view() com os valores padrão rastreia a imagem em relação ao scrollport, que, nesse caso, também é o viewport.

É importante considerar o suporte do navegador e as preferências do usuário, especialmente para necessidades de acessibilidade. Portanto, use a regra @supports para verificar se o navegador oferece suporte a animações com rolagem e envolva a animação com 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 geradas por rolagem podem significar experiências de scrollytelling em toda a página, mas também podem significar animações mais sutis, como uma barra de cabeçalho minimizada e mostrando uma sombra à medida que você rola um app da Web.

Visualização de animação com 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 frame-chave diferentes, como o cabeçalho, o texto, a barra de navegação e o plano de fundo, e aplica a respectiva animação movida por rolagem a cada uma delas. Embora cada um tenha um estilo de animação diferente, todos têm a mesma linha do tempo de animação, o scroller mais próximo e o mesmo intervalo de animação, da parte de cima da página até 150 pixels.

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

Essa API integrada reduz a carga de código que você precisa manter, seja um script personalizado que você escreveu ou a inclusão de uma dependência de terceiros extra. Isso também elimina a necessidade de enviar vários observadores de rolagem, o que significa alguns benefícios de desempenho bastante significativos. Isso acontece porque as animações movidas por rolagem funcionam fora da 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 no CSS ou nos hooks do JavaScript.

A Tokopedia usou recentemente animações movidas por rolagem para fazer a barra de navegação de produtos aparecer enquanto você rolava. O uso dessa API trouxe alguns benefícios importantes, tanto para o gerenciamento de código quanto para o desempenho.

As animações de rolagem direcionam a barra de navegação de produtos na Tokopedia conforme você rola a tela para baixo.

"Conseguimos reduzir até 80% das 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 foi reduzido 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 envolvente, e já estamos pensando no que pode vir a seguir. Isso inclui a capacidade de não usar apenas novas linhas do tempo de animação, mas também 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 adicionados aos navegadores no futuro. A demonstração a seguir mostra uma combinação desses recursos futuros. Ele usa o CSS scroll-start-target para definir a data e a hora iniciais nos seletores e o evento scrollsnapchange do JavaScript para atualizar a data do cabeçalho, facilitando a sincronização dos dados com o evento fixado.

Confira a demonstração ao vivo no Codepen

Também é possível usar isso para atualizar um seletor em tempo real com o evento scrollsnapchanging do JavaScript.

No momento, esses recursos estão disponíveis apenas no Canary com uma flag, mas 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 com rolagem, nossa equipe lançou uma nova série de vídeos no canal do YouTube Chrome for Developers. Aqui, você vai aprender os conceitos básicos das animações com rolagem de Bramus Van Damme, incluindo como o recurso funciona, vocabulário, várias maneiras de criar efeitos e como combinar efeitos para criar experiências ricas. É uma ótima série de vídeos.

Conferir transições

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

Compatibilidade com navegadores

  • Chrome: 111.
  • Edge: 111.
  • Firefox: não é compatível.
  • Safari: 18.

Origem

A 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 tranquila e sem problemas. Isso inclui a barra lateral do editor de listagem, 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 do mesmo documento, como no Airbnb.
O portfólio de Maxwell Barvian, mostrando transições de visualização entre visualizações.

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

A maneira de ativar rapidamente as transições de visualização no seu aplicativo de página única é simples, basta agrupar uma interação usando document.startViewTransition e garantir que cada elemento que está 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;
}

Conferir as 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 de transições de visualização deste ano simplifica esse problema e introduz a capacidade de criar classes de transição de visualização que podem ser aplicadas a animações personalizadas.

Compatibilidade com navegadores

  • Chrome: 125.
  • Edge: 125.
  • Firefox: não é compatível.
  • Safari: 18.2.

Conferir os tipos de transição

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

Compatibilidade com navegadores

  • Chrome: 125.
  • Edge: 125.
  • Firefox: não é compatível.
  • Safari: 18.

Por exemplo, talvez você queira que uma página inicial seja animada para uma página de blog de uma maneira diferente da que essa página de blog é animada de volta para a página inicial. Ou você pode querer que as páginas sejam trocadas de maneiras diferentes, como neste exemplo, indo da esquerda para a direita e vice-versa. Antes, isso era confuso. Era possível adicionar classes ao DOM para aplicar estilos e depois removê-las. Os tipos de transição de visualização permitem que o navegador limpe transições antigas em vez de exigir que você faça isso manualmente antes de iniciar novas transições, 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 sua expansão. Muitos aplicativos não são apenas uma página, mas uma tapeçaria robusta com várias páginas. Por isso, estamos felizes em 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.

Compatibilidade com navegadores

  • Chrome: 126.
  • Edge: 126.
  • Firefox: não é compatível.
  • Prévia da tecnologia do Safari: compatível.

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

Uma das principais diferenças nas transições de visualização do mesmo documento é que você não precisa encerrar a transição com document.startViewTransition(). Em vez disso, ative as duas páginas envolvidas na transição de visualização usando a regra at-rule @view-transition do CSS.

@view-transition {
  navigation: auto;
}

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

Com pageswap, você pode fazer algumas mudanças de última hora na página de saída antes que os snapshots antigos sejam feitos. Com 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 um subárvore DOM, permitindo que o restante da página continue interativo e oferecendo suporte a várias transições de visualização executadas ao mesmo tempo.
  • Transições de visualização geradas por gestos: use gestos de arrastar ou deslizar para acionar uma transição de visualização entre documentos e ter experiências mais parecidas com a Web.
  • Correspondência de navegação no CSS: personalize sua transição de visualização entre documentos diretamente no CSS como uma alternativa ao uso de eventos pageswap e pagereveal no JavaScript. Para saber mais sobre transições de visualização para aplicativos com várias páginas, incluindo como configurá-las com melhor desempenho usando a pré-renderização, confira a seguinte palestra de Bramus Van Damme:

Componentes de interface ativados pelo mecanismo: simplificação de interações complexas

Criar aplicativos da Web complexos não é uma tarefa 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 em criar ótimas experiências. Isso é feito por meio de um esforço colaborativo que envolve vários órgãos de padronização e grupos da comunidade, 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 é uma solicitação 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 o layout e a renderização até a rolagem e interação, o estilo do agente do usuário e as propriedades do CSS, e até mesmo as mudanças no próprio HTML.

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

Um menu suspenso é composto por muitas partes e inclui muitos estados que precisam ser considerados, como:

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

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

A API Popover

Primeiro, lançamos um atributo global chamado popover, que alcançou o status de disponibilidade da versão de referência há algumas semanas.

Compatibilidade com navegadores

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

Origem

Os elementos de pop-up ficam ocultos com display: none até serem abertos com um invocador, como um botão ou com JavaScript. Para criar um pop-up básico, defina o atributo pop-up no elemento e vincule o ID dele a um botão usando popovertarget. 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 de popover ativado, o navegador processa muitos comportamentos importantes sem nenhum script adicional, incluindo:

  • Promoção para a camada superior: Uma camada separada acima do restante da página, para que você não precise mexer em z-index.
  • Funcionalidade de dispensa leve: Clicar fora da área do pop-up fecha o pop-up e retorna o foco.
  • Gerenciamento de foco de guia padrão: Abrir o pop-up faz com que a próxima guia pare dentro dele.
  • Vinculação de teclado integrada: Pressionar a tecla esc ou alternar duas vezes fecha o pop-up e retorna o foco.
  • Vinculação de componentes padrão. : O navegador conecta semanticamente um popover ao gatilho.
Tela inicial do GitHub
Menu na página inicial do GitHub.

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

"Conseguimos descontinuar literalmente milhares de linhas de código migrando para o pop-up. O Popover nos ajuda a eliminar 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 os comportamentos de foco integrados facilitam muito a implementação de padrões pelo nosso sistema de design da maneira certa.-Keith Cirkel, engenheiro de software, GitHub"

Como animar efeitos de entrada e saída

Quando você tiver pop-ups, provavelmente vai querer adicionar alguma interação. No ano passado, foram lançados quatro novos recursos de interação para oferecer suporte à animação de popovers. São eles:

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

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

Compatibilidade com navegadores

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

Origem

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

Compatibilidade com navegadores

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

Origem

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

Compatibilidade com navegadores

  • Chrome: 117.
  • Edge: 117.
  • Firefox: não é compatível.
  • Safari: não é compatível.

Origem

Essas propriedades funcionam para qualquer elemento que você esteja animando na camada superior, seja um pop-up ou uma caixa de diálogo. O resultado final é este:

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 para esse elemento no DOM. Isso é feito para a caixa de diálogo e o plano de fundo. Em seguida, estilize o estado aberto para a caixa de diálogo e o plano de fundo. Para uma caixa de diálogo, ele usa o atributo open e, para um pop-up, o pseudoelemento ::popover-open. Por fim, anime o 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 de âncora

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

Compatibilidade com navegadores

  • Chrome: 125.
  • Edge: 125.
  • Firefox: não é compatível.
  • Safari: não é compatível.

Origem

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 abaixo, uma dica simples é ancorada em cada botão, posicionada na parte de baixo, no centro.

Demonstração visual

Demonstração ao vivo

Configure uma relação de posicionamento de âncora no CSS usando a propriedade anchor-name no elemento de âncora (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 abaixo posiciona a parte de cima da dica de ferramenta na parte de baixo do botão.

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

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

Como alternativa, use o nome da âncora diretamente na função de âncora e ignore 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 para centralizar o elemento posicionado na â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 pop-up, ele definitivamente 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 sendo ancorado aos itens da lista quando você passa o cursor ou clica neles.

Demonstração visual

Demonstração ao vivo

Este exemplo usa a função de âncora para configurar a posição da âncora 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 muda o destino para aplicar o posicionamento, animando a cor ao mesmo tempo para criar um efeito legal.

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 antes, há um novo mecanismo de layout incluído que foi lançado como parte da API de posicionamento de âncora chamada área de inserção. A área de inserção facilita a colocação de elementos posicionados em relação às respectivas âncoras e funciona em uma grade de 9 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 todas as colunas ou linhas disponíveis. Você também pode usar propriedades lógicas. Para facilitar a visualização e a escolha desse mecanismo de layout, confira esta ferramenta no Chrome 125 e versões mais recentes:

Como esses elementos estão ancorados, o elemento posicionado se move dinamicamente pela página conforme a âncora se move. Nesse caso, temos elementos de card com estilo de consulta 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 fixado muda com o novo layout conforme a interface do card muda.

Demonstração visual

Demonstração ao vivo

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

Os menus e a navegação de submenus são muito mais fáceis de criar com uma combinação de posicionamento de pop-up e âncora. E, quando você atinge a borda de uma viewport com o elemento ancorado, também é possível permitir que o navegador gerencie a mudança de posicionamento. Isso pode ser feito de algumas maneiras. A primeira é criar suas próprias regras de posicionamento. Neste caso, o submenu é posicionado inicialmente à direita do botão "loja". No entanto, é possível 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 ancorados, tentando a posição certa primeiro e depois mudando para a parte de baixo. Isso pode ser feito com uma boa transição.

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ícita, há algumas palavras-chave que o navegador fornece se você quiser algumas interações básicas, como inverter a âncora no bloco ou nas direções inline.

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

Para uma experiência simples, aproveite esses valores de palavras-chave e pule a definição de position-try. Agora você pode ter um elemento posicionado com âncora totalmente funcional e responsivo ao local 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 o uso do posicionamento de âncora.

O futuro da interface em camadas

As experiências com cabos estão 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, atualmente popover só funciona com botões como o elemento de invocação ou com JavaScript. Para algo como as visualizações no estilo da Wikipedia, um padrão encontrado em toda a plataforma da Web, é necessário que seja possível interagir e também acionar um pop-up de um link e do usuário mostrando interesse sem necessariamente clicar, como um foco de cursor ou guia.

Como próxima etapa da API de pop-up, estamos trabalhando com interesttarget para atender a essas necessidades e facilitar a recriação dessas experiências com os hooks de acessibilidade adequados integrados. Esse é um problema de acessibilidade desafiador de resolver, com muitas perguntas abertas sobre os comportamentos ideais, mas resolver e normalizar essa funcionalidade no nível da 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. invoketarget oferece suporte à experiência declarativa do desenvolvedor que popovertarget oferece pop-ups, 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 há casos de uso que ainda não são cobertos por essa API. Por exemplo, estilizar a seta que conecta um elemento ancorado à âncora, especialmente quando a posição do elemento ancorado muda, e permitir que um elemento "deslize" e permaneça na viewport em vez de encaixar em outro conjunto de posições quando ele atinge a caixa delimitadora. Estamos animados com essa API poderosa, mas também queremos expandir ainda mais os recursos dela no futuro.

Seleção com estilo

Usando popover e anchor juntos, a equipe fez progressos 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 momento. No entanto, estou feliz em compartilhar algumas demonstrações ao vivo e atualizações sobre nosso progresso e espero receber seu feedback. Primeiro, houve progressos em como os usuários podem optar pela nova experiência de seleção personalizável. A maneira atual de fazer isso é usar uma propriedade de aparência no 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 agrupar as opções em um datalist para personalização e a capacidade de adicionar conteúdo não interativo arbitrário, como imagens, nas opções. Você também terá acesso a um novo elemento, <selectedoption>, que vai refletir o conteúdo das opções em si, que você pode personalizar de acordo com suas necessidades. Esse elemento é muito útil.

Demonstração visual

demonstração de bandeira

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 de visualização. 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 da reutilização do elemento <select> para essa API é a compatibilidade com versões anteriores. Nessa seleção de país, você pode conferir uma interface personalizada com imagens de bandeiras nas opções para facilitar a análise do conteúdo pelo usuário. Como os navegadores sem suporte 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 padrão de seleção atual.

O navegador sem suporte recebe a experiência de seleção atual.
Visualização do navegador compatível à esquerda e fallback do navegador não compatível à direita.

Com as opções personalizáveis, as possibilidades são infinitas. Eu particularmente adoro esse seletor de país no estilo do Airbnb porque ele tem um estilo inteligente para design responsivo. Você pode fazer isso e muito mais com o próximo elemento de seleção estilizável, tornando-o uma adição muito necessária à plataforma da Web.

Demonstração visual

Demonstração ao vivo

Accordion exclusivo

A solução de estilo de seleção (e todas as peças que acompanham) não é o único componente de interface em que a equipe do Chrome está se concentrando. 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

Compatibilidade com navegadores

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

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

Demonstração de acordeão exclusivo
<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 interagido 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.

Compatibilidade com navegadores

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

Origem

Demo Screencast

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 mais sobre o uso de pseudoelementos de validação de formulário user-*.

field-sizing: content

Outra atualização útil de componentes lançada recentemente é o field-sizing: content, que pode ser aplicado a controles de formulário, como inputs e textareas. Isso permite que o tamanho da entrada aumente (ou diminua) dependendo do conteúdo. field-sizing: content pode ser particularmente útil para textareas, já que você não precisa mais resolver tamanhos fixos em que talvez precise rolar para cima para ver o que escreveu nas partes anteriores do comando em uma caixa de entrada muito pequena.

Compatibilidade com navegadores

  • Chrome: 123.
  • Edge: 123.
  • Firefox: não é compatível.
  • Safari: não é compatível.

Origem

Demo Screencast

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 elemento de regra horizontal em opções, é outro recurso de componente pequeno, mas útil. Embora isso não tenha muito uso semântico, ele ajuda a separar o conteúdo em uma lista de seleção, especialmente o conteúdo que você não quer agrupar com um grupo de opções, como um valor de marcador de posição.

Selecionar captura de tela

captura de tela de hr em seleção 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 a linha horizontal em opções.

Melhorias na qualidade de vida

Estamos sempre iterando, e não apenas para interações e componentes. No ano passado, lançamos muitas outras atualizações de qualidade de vida.

Anilhamento com antecipação

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

Compatibilidade com navegadores

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

Origem

Uma das minhas coisas favoritas sobre o aninhamento de CSS é que ele permite bloquear visualmente os componentes e, dentro deles, incluir estados e modificadores, como consultas de contêiner e de mídia. Antes, eu tinha o hábito de agrupar todas essas consultas na parte inferior do arquivo para fins de especificidade. Agora, você pode escrever 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 */
  }
}

Align-content para layout de bloco

Outra mudança muito legal é 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 um div sem precisar aplicar o layout flex ou de grade e sem efeitos colaterais, como evitar o colapso de margem, que você pode não querer nesses algoritmos de layout.

Compatibilidade com navegadores

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

Captura de tela

Demonstração ao vivo

div {
  align-content: center;
}

Quebra de texto: equilíbrio e beleza

Falando em layout, o layout de texto teve 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 os singletons na última linha do texto.

Demo Screencast

Demonstração ao vivo

Na demonstração a seguir, você pode comparar, arrastando o controle deslizante, os efeitos de balance e pretty em um título 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

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

Compatibilidade com navegadores

  • Chrome: 119.
  • Edge: 119.
  • Firefox: não é compatível.
  • Safari: não é compatível.

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

E text-spacing-trim, que aplica o espaçamento entre caracteres de pontuação para melhorar a legibilidade da tipografia em chinês, japonês e coreano e gerar resultados mais agradáveis visualmente.

Compatibilidade com navegadores

  • Chrome: 123.
  • Edge: 123.
  • Firefox: não é compatível.
  • Safari: não é compatível.

Origem

A metade direita do período CJK é removida com text-spacing-trim.
Quando os caracteres de pontuação aparecem em uma linha, a metade direita do ponto CJK precisa ser removida.

Sintaxe de cor relativa

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

Neste exemplo, as cores usam a organização de temas baseada em Oklch. Conforme o valor de matiz é ajustado com base no controle deslizante, todo o tema muda. Isso pode ser feito com a sintaxe de cor relativa. 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 a progressão com propriedades personalizadas e sintaxe de cores relativa para criar temas.

Demo Screencast

Demonstração ao vivo

Na demonstração a seguir, você pode comparar, arrastando o controle deslizante, os efeitos de balance e pretty em um título 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()

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

Compatibilidade com navegadores

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

Origem

A função light-dark() é uma melhoria ergonômica que simplifica as opções de tema 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, você pode 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 saber mais.
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 fundo azul-claro. Se o usuário tiver selecionado um tema escuro, o botão terá um fundo azul-escuro.

Seletor de :has()

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

Compatibilidade com navegadores

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

Origem

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

Demonstração de has() sendo usado 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(), conseguimos eliminar a validação baseada em JavaScript da seleção do usuário e substituí-la por uma solução de CSS que funciona perfeitamente para nós com a mesma experiência de antes.–Aman Soni, líder de tecnologia, PolicyBazaar"

Consultas em contêiner

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

Compatibilidade com navegadores

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

Origem

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

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

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

Demo Screencast

Demonstração ao vivo

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

@property

E, em breve, vamos lançar a @property na versão padrão. Esse é um recurso importante para fornecer significado semântico a propriedades CSS personalizadas (também conhecidas como variáveis CSS) e ativar vários novos recursos de interação. @property também permite significado contextual, verificação de tipo, padrões e valores substitutos no 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 muita profundidade à linguagem CSS.

Compatibilidade com navegadores

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

Origem

Demo Screencast

Demonstração ao vivo

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

Conclusão

Com todos esses novos recursos poderosos de interface em todos os navegadores, as possibilidades são infinitas. Novas experiências interativas com animações e transições de visualização movidas por rolagem tornam a Web mais fluida e interativa de maneiras nunca vistas antes. E os componentes de interface de nível avançado facilitam a criação de componentes robustos e personalizados sem precisar 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 as pequenas coisas, 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ê pode remover scripts de terceiros para recursos com alto desempenho, como scrollytelling e tethering de elementos com posicionamento de âncora, criar transições de página fluidas, estilizar menus suspensos e melhorar a estrutura geral do código de forma nativa.

Nunca houve um momento melhor para ser um desenvolvedor da Web. Não houve tanta energia e empolgação desde o anúncio do CSS3. Recursos que precisávamos, mas só podíamos sonhar em lançar no passado, finalmente estão se tornando realidade e fazendo parte da plataforma. E é por causa da sua opinião que podemos priorizar e, finalmente, dar vida a esses recursos. Estamos trabalhando para facilitar a realização de tarefas difíceis e tediosas de forma nativa, para que você possa passar mais tempo criando as coisas que importam, como os recursos principais e os detalhes de design que diferenciam sua marca.

Para saber mais sobre esses novos recursos, acompanhe as novidades em developer.chrome.com e web.dev, onde nossa equipe compartilha as últimas notícias sobre tecnologias da Web. Teste animações com rolagem, transições de visualização, posicionamento de âncora ou até mesmo o estilo de seleção e nos conte o que achou. Estamos aqui para ouvir e ajudar.