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

A plataforma da Web está viva com a inovação, com CSS e recursos de interface da Web na vanguarda dessa incrível evolução. Estamos vivendo em uma era de ouro para a interface de usuário da Web, com novos recursos de CSS sendo lançados nos navegadores em um ritmo nunca visto antes, abrindo um mundo de possibilidades para a criação de experiências na Web belas e envolventes. Esta postagem do blog explica em detalhes o estado atual do CSS e explora 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

A experiência na Web é fundamentalmente uma chamada e resposta entre você e seus usuários. Por isso, é tão importante investir em interações de qualidade do usuário. Estamos trabalhando em algumas melhorias realmente grandes que disponibilizam recursos que nunca tivemos antes na Web para navegar dentro de páginas da Web e navegar entre elas.

Animações de rolagem

Compatibilidade com navegadores

  • 115
  • 115
  • x

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 da rolagem de um botão para iniciar, pausar e inverter uma animação. Ao rolar para frente, você verá a animação progredir e, ao rolar para trás, o processo será inverso. Isso permite criar recursos visuais parciais ou de página inteira com elementos animados dentro e dentro da janela de visualização, também conhecido como scrollytelling, para gerar impacto visual dinâmico.

Animações de rolagem podem ser usadas para destacar conteúdos importantes, guiar os usuários ao longo de uma história ou simplesmente adicionar um toque dinâmico às suas páginas da Web.

Visual de animação de 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 à janela de rolagem (que nesse caso também é a janela de visualização).

É 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 é compatível com animações de rolagem e envolva-a em uma consulta de preferência do usuário, como @media (prefers-reduced-motion: no-preference), para respeitar essas preferências. Depois de fazer essas verificações, você sabe que seus estilos funcionarão 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 */
  }
}

Animações de rolagem podem significar experiências de rolagem de página inteira, mas também podem significar animações mais sutis, como uma barra de cabeçalho minimizando e mostrando uma sombra ao rolar um app da Web.

Visual de animação de 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 (cabeçalho, texto, barra de navegação e plano de fundo) e, em seguida, aplica a respectiva animação de 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 botão de rolagem mais próximo e o mesmo intervalo de animação, da parte superior 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ê criou ou a inclusão de uma dependência adicional de terceiros. Isso também elimina a necessidade de enviar vários observadores de rolagem, o que significa alguns benefícios de desempenho bastante significativos. Isso ocorre porque as animações de 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 os ganchos do JavaScript.

A Tokopedia recentemente usou animações de rolagem para que a barra de navegação do produto aparecesse conforme você rolava. O uso dessa API gerou alguns benefícios sérios, tanto para o gerenciamento de código quanto para o desempenho.

As animações de rolagem impulsionam essa barra de navegação do produto na Tokopedia conforme 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 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 continuarão a tornar a Web um lugar mais envolvente 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, chamada de animações acionadas por rolagem.

E há ainda mais recursos de rolagem que serão lançados nos navegadores no futuro. A demonstração a seguir mostra uma combinação desses futuros recursos. Ela 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 alinhado.

Veja a demonstração ao vivo no Codepen

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

Esses recursos específicos estão atualmente apenas no Canary, mas eles desbloqueiam recursos antes 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 de rolagem, nossa equipe acabou de lançar uma nova série de vídeos, disponível no canal Chrome for Developers do YouTube. Aqui, você vai aprender o básico sobre animações de rolagem do canal Bramus Van Damme, incluindo como o recurso funciona, vocabulário, várias maneiras de criar efeitos e como combinar efeitos para criar experiências mais completas. É uma ótima série de vídeos para conferir.

Ver transições

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

Compatibilidade com navegadores

  • 111
  • 111
  • x
  • x

Origem

O Airbnb é uma das empresas que já estão testando a integração de transições de visualização na interface para proporcionar uma experiência de navegação na Web tranquila e integrada. Isso inclui a barra lateral do editor de fichas, para a edição de fotos e a adição de comodidades, tudo em um fluxo fluido de usuário.

Uma transição de visualização do mesmo documento vista no Airbnb.
O portfólio de Maxwell Barvian, que mostra as transições entre visualizações.

Embora esses efeitos de página inteira sejam bonitos e simples, também é possível criar microinterações, como neste exemplo, em que a visualização de lista é atualizada com a interação do usuário. Esse efeito pode ser conseguido sem esforço com transições de visualização.

Ativar rapidamente as transições de visualização no aplicativo de página única é tão simples quanto 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 à medida que você cria nós do 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 das transições de visualização podem ser usados para aplicar animações personalizadas à transição de visualização, embora isso possa ser complicado com a transição de muitos elementos. A primeira atualização para transições de visualização este 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.

Compatibilidade com navegadores

  • 125
  • 125
  • x
  • x

Ver tipos de transição

Outra grande melhoria para as transições de visualização é o suporte aos 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 criar animações de e para visualizações de páginas.

Por exemplo, talvez você queira que a animação de uma página inicial leve à página de um blog de uma forma diferente da animação de voltar à página inicial. Ou talvez você queira que as páginas apareçam e saiam de maneiras diferentes, como neste exemplo, indo da esquerda para a direita e vice-versa. Antes, isso era confuso. Você podia adicionar classes ao DOM para aplicar estilos e depois precisava remover as classes. 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 da paginação. Os tipos determinam qual animação usar. Os estilos são separados na folha de estilos 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 é como ela é expansiva. Muitos aplicativos não são apenas uma única página, mas uma tapeçaria robusta contendo várias páginas. Por isso, temos o prazer de anunciar que estamos lançando o suporte para transições de visualização entre documentos em aplicativos de várias páginas no Chromium 126.

Compatibilidade com navegadores

  • 126
  • 126
  • x
  • x

Origem

Esse novo conjunto de recursos entre documentos inclui experiências da Web da mesma origem, como navegar de web.dev para web.dev/blog, mas isso não inclui navegar 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 do mesmo documento é que você não precisa unir a transição com document.startViewTransition(). Em vez disso, ative as duas páginas envolvidas na transição de visualização usando a regra de CSS @view-transition.

@view-transition {
  navigation: auto;
}

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

Com o pageswap, é possível fazer algumas mudanças de última hora na página de saída antes que os snapshots antigos sejam criados. Com pagereveal, é possível personalizar a nova página antes que ela comece a ser renderizada depois de ser inicializada.

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

window.addEventListener('pagereveal', async (e) => {
    // ...
});
Mostrar 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 para uma subárvore do DOM, permitindo que o restante da página continue sendo interativo e oferecendo suporte a várias transições de visualização em execução ao mesmo tempo.
  • Transições de visualização por gestos: use gestos de arrastar ou deslizar para acionar uma transição de visualização de vários documentos e criar experiências mais nativas na Web.
  • Correspondência de navegação no CSS: personalize a transição da visualização de vários documentos diretamente no CSS como uma alternativa ao uso de eventos pageswap e pagereveal no JavaScript Para saber mais sobre as transições de visualização em 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 para mecanismo: simplificando interações complexas

Criar aplicativos da web complexos não é uma tarefa fácil, mas CSS e HTML estão evoluindo para tornar esse processo muito mais gerenciável. Os novos recursos e melhorias estão simplificando a criação de componentes de IU, permitindo que você se concentre na criação de ótimas experiências. Isso é feito por meio de um esforço colaborativo que envolve vários órgãos de normalização e grupos comunitários importantes, incluindo o grupo de trabalho do CSS, o grupo da comunidade Open UI e o WhatWG (Web Hypertext Application Technology Working Group).

Um grande ponto problemático dos desenvolvedores é uma solicitação aparentemente simples: a capacidade de estilizar menus suspensos (o elemento de seleção). Embora pareça simples superficialmente, este é um problema complexo, que toca em muitas partes da plataforma, desde layout e renderização até rolagem e interação, estilização do user agent e propriedades CSS e até alterações no próprio HTML.

Selecione uma lista de dados com opções, botão de gatilho, seta indicadora e opção selecionada.
Detalhar as partes de um elemento select

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

  • Vinculações de teclado (para entrar/sair da interação)
  • Clique para dispensar
  • Gerenciamento ativo de pop-over (fechar outros pop-ups quando um for aberto)
  • Gerenciamento de foco na guia
  • Visualização do valor da opção selecionada
  • Estilo de interação com a seta
  • Gerenciamento de estado (aberto/fechado)

No momento, é difícil gerenciar todo esse estado por conta própria, mas a plataforma também não facilita. Para corrigir isso, dividimos esses elementos e estamos lançando alguns recursos primitivos que vão permitir a aplicação de estilos em menus suspensos, mas também vão fazer muito mais.

A API Popover

Primeiro, enviamos um atributo global chamado popover, que acabou de atingir o status de disponibilidade de referência recentemente.

Compatibilidade com navegadores

  • 114
  • 114
  • 125
  • 17

Origem

Os elementos de popover ficam ocultos com display: none até que sejam abertos com um invocador, como um botão, ou com JavaScript. Para criar um pop-over básico, defina o atributo pop-over 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 lida com 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 no z-index.
  • Funcionalidade de dispensa simples.: Clicar fora da área do pop-up vai fechá-lo e retornar o foco.
  • Gerenciamento de foco na guia padrão: Abrir o pop-over faz a próxima guia parar dentro dele.
  • Vinculações de teclado integradas: Pressionar a tecla esc ou alternar duas vezes fechará o pop-over e retornará o foco.
  • Vinculações padrão de componentes. : o navegador conecta semanticamente um pop-up ao seu acionador.
Tela inicial do GitHub
Menu na página inicial do GitHub.

Você pode até estar usando essa API pop-over hoje sem perceber. O GitHub implementou o pop-up no menu “novo” da página inicial e na visão geral da análise da solicitação de envio. Eles aprimoraram esse recurso progressivamente usando o polyfill popover, criado pela Oddbird com suporte significativo do próprio Keith Cirkel do GitHub, para oferecer suporte a navegadores mais antigos.

"Conseguimos descontinuar literalmente milhares de linhas de código migrando para o popover. O Popover nos ajuda eliminando a necessidade de lutar contra os números mágicos de Z-index... ter a relação de árvore de acessibilidade correta estabelecida com comportamento declarativo de botão e comportamentos de foco integrados torna muito mais fácil para nosso sistema de design implementar padrões da maneira correta. Keith Cirkel, engenheiro de software, GitHub"

Animar efeitos de entrada e saída

Quando há pop-ups, é recomendável adicionar alguma interação. Há quatro novos recursos de interação lançados no ano passado para ajudar a animar pop-ups. São elas:

A capacidade de animar display e content-visibility na linha do tempo de um frame-chave.

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

Compatibilidade com navegadores

  • 117
  • 117
  • 17,4

Origem

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

Compatibilidade com navegadores

  • 117
  • 117
  • x
  • 17,5

Origem

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

Compatibilidade com navegadores

  • 117
  • 117
  • x
  • x

Origem

Essas propriedades funcionam para qualquer elemento que você esteja animando na camada superior, seja um pop-over ou uma caixa de diálogo. Juntamente, ele tem esta aparência em uma caixa de diálogo com um pano 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 a @starting-style para que o navegador saiba a quais estilos animar esse elemento no DOM. Isso é feito na caixa de diálogo e no pano de fundo. Em seguida, defina o estilo do estado aberto para a caixa de diálogo e o pano de fundo. Para uma caixa de diálogo, usa o atributo open e, para um pop-up, 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 âncora agora está disponível a partir do Chrome 125.

Compatibilidade com navegadores

  • 125
  • 125
  • x
  • x

Origem

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

Demonstração visual

Demonstração ao vivo

Configure uma relação de posição de âncora no 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 superior da dica na parte inferior 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 pule a propriedade position-anchor. Isso pode ser útil ao fixar 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 âncoras, o pop-over definitivamente não é um requisito para o uso do posicionamento de âncoras. O posicionamento da â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 para listar itens conforme você passa o mouse ou a tecla Tab sobre eles.

Demonstração visual

Demonstração ao vivo

Este exemplo usa a função "Âncora" para configurar a posição da âncora usando as propriedades físicas de left, right e bottom. Quando você passa o mouse sobre um dos links, a âncora alvo muda, e o navegador muda o alvo para aplicar o posicionamento, além de animar 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 antes, há um novo mecanismo de layout incluído que foi usado como parte da API de posicionamento de âncoras chamado área de encarte. A área inserida facilita o posicionamento 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 superior e inset-area: bottom posiciona o elemento posicionado na parte inferior.

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;
}

É possível combinar esses valores de posição com palavras-chave de período para começar na posição central e abranger para a esquerda, para a direita ou abranger tudo para ocupar o conjunto completo de colunas ou linhas disponíveis. Você também pode usar propriedades lógicas. Para facilitar a visualização desse mecanismo de layout, confira esta ferramenta no Chrome 125 ou posterior:

Como esses elementos estão ancorados, o elemento posicionado se move dinamicamente pela página conforme a âncora se move. Neste 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 ancorado muda com o novo layout quando a interface do cartão muda.

Demonstração visual

Demonstração ao vivo

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

É muito mais fácil criar menus e a navegação do submenu com uma combinação de posicionamento de pop-up e de âncora. E, ao atingir a borda de uma janela de visualização com seu elemento ancorado, você também pode deixar que o navegador lide com a mudança de posicionamento para você. É possível fazer isso 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, fornecendo um identificador personalizado de --bottom. Em seguida, você conecta esse bloco @position-try à âncora usando position-try-options.

Agora, o navegador alternará entre esses estados ancorados, tentando primeiro a posição correta e, em seguida, movendo para a parte inferior. E 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);
}

Junto com a lógica de posicionamento explícito, existem algumas palavras-chave que o navegador fornece se você quiser algumas interações básicas, como virar a âncora no bloco ou nas 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 gravação de uma definição de position-try. Agora, você pode ter um elemento posicionado como âncora responsivo ao local totalmente funcional 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 â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 soltar a criatividade e melhorar o controle sobre os elementos posicionados como âncora e as interfaces em camadas. Mas este é apenas o começo. Por exemplo, no momento, popover só funciona com botões como o elemento invocado ou com JavaScript. Para algo como as visualizações no estilo da Wikipédia, um padrão visto em toda a plataforma da Web, é preciso que seja possível interagir com ele e acionar um pop-over de um link e do usuário mostrando interesse sem necessariamente clicar, como passar o cursor ou focar em uma guia.

Como próxima etapa para a API popover, estamos trabalhando no interesttarget para resolver essas necessidades e facilitar a recriação das experiências com os ganchos de acessibilidade adequados integrados. Esse é um problema de acessibilidade desafiador de se resolver, com muitas questões em aberto sobre 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. O invoketarget é compatível com a experiência declarativa do desenvolvedor em que o popovertarget fornece 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, definir o estilo da 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 janela de visualização em vez de se ajustar a outra posição definida quando ele atingir a caixa delimitadora. Estamos felizes em lançar essa API avançada, mas queremos ampliar os recursos ainda mais no futuro.

Seleção estilizável

Usando popover e anchor juntos, a equipe está progredindo 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 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 um progresso em relação à opção de incluir os usuários na 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 de definir a aparência, você vai participar de uma experiência de seleção nova e personalizável.

select {
  appearance: base-select;
}

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

Demonstração visual

demonstração de sinalização

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 abaixo demonstra a personalização da <selectedoption> na interface do Gmail, em que um ícone visual representa o tipo de resposta selecionado para economizar espaço. Você pode usar estilos de exibição básicos no selectedoption para diferenciar o estilo da opção do estilo de visualização. Nesse caso, o texto mostrado na opção pode ficar oculto visualmente na selectedoption.

Demonstração visual

demonstração do gmail

Demonstração ao vivo

selectedoption .text {
  display: none;
}

Uma das maiores vantagens em reutilizar o elemento <select> nessa API é a compatibilidade com versões anteriores. Nesta 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 incompatíveis ignoram as linhas que não entendem, como o botão personalizado, datalist, selectedoption e imagens nas opções, o substituto será semelhante à interface de seleção padrão atual.

Um navegador sem suporte recebe a experiência de seleção atual.
Imagem do navegador compatível à esquerda versus substituto de navegador incompatível à direita.

Com seleções personalizáveis, as possibilidades são infinitas. Particularmente, amo esse seletor de país no estilo Airbnb porque ele tem um estilo inteligente para o design responsivo. Você pode fazer isso e muito mais com a próxima seleção estilizável, tornando-a uma adição muito necessária à plataforma web.

Demonstração visual

Demonstração ao vivo

Acordeão exclusivo

Resolver um determinado estilo (e todos os elementos que o acompanham) não é o único componente de IU 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

  • 120
  • 120
  • x
  • 17,2

Para isso, é possível aplicar o mesmo valor de nome a vários elementos de detalhes, criando um grupo conectado de detalhes, semelhante a um grupo de botões de opção.

Demonstração exclusiva do accordion
<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 dos componentes de interface são as pseudoclasses :user-valid e :user-invalid. Estável 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 interagiu significativamente com a entrada. Isso significa que é necessário muito menos código para determinar se houve interação com o valor de um formulário ou se ele ficou "sujo", o que pode ser muito útil para fornecer feedback aos usuários e reduzir muitos scripts que seriam necessários para fazer isso no passado.

Compatibilidade com navegadores

  • 119
  • 119
  • 88
  • 16,5

Origem

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

field-sizing: content

Outra atualização de componente útil que foi lançada recentemente é a field-sizing: content, que pode ser aplicada a controles de formulários, como entradas e áreas de texto. Isso permite que o tamanho da entrada aumente (ou diminua) dependendo do conteúdo. O field-sizing: content pode ser útil principalmente para áreas de texto, já que você não tem mais tamanhos fixos em que talvez precise rolar para cima para conferir o que escreveu em uma caixa de entrada muito pequena para conferir o que escreveu nas partes anteriores do comando.

Compatibilidade com navegadores

  • 123
  • 123
  • x
  • x

Screencast de demonstração

Demonstração ao vivo

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

Saiba mais sobre o dimensionamento do campo.

<hr> em <select>

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

Selecionar captura de tela

captura de tela da seleção com um tema claro e escuro no Chrome

Selecionar "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 in select.

Melhorias na qualidade de vida

Estamos constantemente iterando, e isso não é apenas para interações e componentes. Muitas outras atualizações sobre qualidade de vida foram implementadas no último ano.

Aninhamento com olhar para frente

O aninhamento de CSS nativo foi usado em todos os navegadores no ano passado e, desde então, foi aprimorado para oferecer suporte ao lançamento. Isso significa que o & antes dos nomes dos elementos não é mais um requisito. Isso faz com que o aninhamento seja muito mais ergonômico e semelhante ao que eu me acostumava no passado.

Compatibilidade com navegadores

  • 120
  • 120
  • 117
  • 17,2

Origem

Uma das minhas coisas favoritas sobre o aninhamento de CSS é que ele permite bloquear visualmente componentes e, dentro desses componentes, inclui estados e modificadores, como consultas de contêiner e de mídia. Anteriormente, eu tinha o hábito de agrupar todas essas consultas na parte inferior do arquivo para fins de especificidade. Agora, é possível escrevê-los de maneira 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 */
  }
}

Alinhar conteúdo para layout em bloco

Outra mudança muito boa é a capacidade de usar mecanismos de centralização como align-content no layout de blocos. Isso significa que agora é possível realizar ações como a centralização vertical em um div sem precisar aplicar um layout flexível ou de grade e sem efeitos colaterais, como evitar o recolhimento da margem, que talvez você não queira desses algoritmos de layout.

Compatibilidade com navegadores

  • 123
  • 123
  • 125
  • 17,4

Captura de tela

Demonstração ao vivo

div {
  align-content: center;
}

Ajustar 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. O text-wrap: balance é usado para um bloco de texto mais uniforme, enquanto o text-wrap: pretty se concentra na redução de Singletons na última linha do texto.

Screencast de demonstração

Demonstração ao vivo

Na demonstração a seguir, você pode fazer uma comparação arrastando o controle deslizante e os efeitos de balance e pretty em um cabeçalho e um parágrafo. Traduza a demonstração para outro idioma.
h1 {
  text-wrap: balance;
}

Saiba mais sobre ajuste de texto: saldo.

Atualizações de tipografia internacional

As atualizações de layout tipográfico para os 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.

Compatibilidade com navegadores

  • 119
  • 119
  • x
  • x

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

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

Compatibilidade com navegadores

  • 123
  • 123
  • x
  • x

A metade direita do período CJK foi removida com o corte de espaço de texto.
Quando os caracteres de pontuação aparecerem em uma linha, a metade direita do período CJK precisa ser removida.

Sintaxe de cor relativa

No mundo dos temas de cores, vimos uma grande atualização na sintaxe de cores relativa.

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

Screencast de demonstração

Demonstração ao vivo

Na demonstração a seguir, você pode fazer uma comparação arrastando o controle deslizante e os efeitos de balance e pretty em um cabeçalho e um parágrafo. Traduza 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 aplicação de temas se tornou muito mais dinâmica e simplificado.

Compatibilidade com navegadores

  • 123
  • 123
  • 120
  • 17,5

Origem

A função light-dark() é uma melhoria ergonômica que simplifica as opções de temas de cores para que você escreva estilos de tema de forma mais concisa, como demonstrado muito bem neste diagrama visual de Adam Argyle. Antes, você precisaria 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 criar essas opções de estilo para temas claros e escuros na mesma linha do CSS usando a função light-dark().

Visualização de light-dark(). Confira 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()

Não vou falar sobre a interface moderna sem mencionar um dos destaques de interoperabilidade mais impactantes do último ano, que é o seletor :has(), que vai ser lançado em todos os navegadores em dezembro do ano passado. Essa API é um divisor de águas para escrever estilos lógicos.

Compatibilidade com navegadores

  • 105
  • 105
  • 121
  • 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 também podem funcionar como um seletor pai.

Demonstração de has() usada 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 definir o estilo dos blocos com base no conteúdo interno. Por exemplo, 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 CSS que funciona perfeitamente com a mesma experiência de antes. - Aman Soni, líder de tecnologia da PolicyBazaar"

Consultas em contêiner

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

Compatibilidade com navegadores

  • 105
  • 105
  • 110
  • 16

Origem

Recentemente, o Angular lançou um belo 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 de várias colunas para um layout de coluna única, os blocos de cabeçalho podem se ajustar automaticamente.

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

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

Screencast de demonstração

Demonstração ao vivo

Como recriar a consulta do contêiner do card do cabeçalho do Angular

@property

E, finalmente, em breve, estamos animados para ver a propriedade @property na linha de base. Esse é um recurso importante para dar significado semântico às propriedades personalizadas do CSS (também conhecidas como variáveis CSS) e oferece vários novos recursos de interação. O @property também ativa significado de contexto, verificação de tipo, padrões e valores substitutos em CSS. Abra 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 do CSS.

Compatibilidade com navegadores

  • 85
  • 85
  • 16.4

Origem

Screencast de demonstração

Demonstração ao vivo

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

Conclusão

Com todos esses novos e poderosos recursos de interface chegando em vários navegadores, as possibilidades são infinitas. Novas experiências interativas com animações de rolagem e transições de visualização tornam a Web mais fluida e interativa de maneiras nunca vistas antes. Os componentes de IU de última geração facilitam mais do que nunca a criação de componentes robustos e belamente personalizados sem prejudicar a experiência nativa. E, por fim, melhorias na qualidade de vida em arquitetura, layout, tipografia e design responsivo não apenas resolvem os pequenos detalhes, mas também fornecem aos desenvolvedores as ferramentas necessárias para criar interfaces complexas que funcionam em uma variedade de dispositivos, formatos e necessidades do usuário.

Com esses novos recursos, será possível remover scripts de terceiros para recursos com alto desempenho, como rolagem de rolagem e elementos de tethering entre si com posicionamento âncora, criar transições fluidas nas páginas, estilizar menus suspensos e melhorar a estrutura geral do código de maneira nativa.

Nunca houve um momento melhor para ser um desenvolvedor Web. Não houve muita energia e empolgação desde o anúncio do CSS3. Os recursos que precisávamos, mas que só sonávamos, agora estão finalmente se tornando realidade e parte da plataforma. E é graças a sua voz que podemos priorizar e finalmente dar vida a essas capacidades. Estamos trabalhando para facilitar as tarefas difíceis e tediosas de forma nativa. Assim, você pode dedicar mais tempo à criação do que realmente importa, como os recursos principais e os detalhes de design que diferenciam sua marca.

Para saber mais sobre esses novos recursos conforme eles forem lançados, acompanhe em developer.chrome.com e web.dev, onde nossa equipe compartilha as novidades sobre tecnologias da Web. Teste animações de rolagem, transições de visualização, posicionamento de âncoras ou até mesmo a seleção estilizável e nos conte o que achou. Estamos aqui para ouvir e ajudar.