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
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. Assim, conforme você rola para frente, a animação avança, e quando você rola para trás, ela vai na direção oposta. 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.
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.
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 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, em seguida, 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 é 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 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 eles 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ê escreveu ou a inclusão de uma dependência de terceiros extra. Ele 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.
"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 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 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.
Também é possível 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, 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, que você encontra no canal do Chrome para desenvolvedores no YouTube. 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.
Ver 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 criar transições perfeitas entre visualizações diferentes de uma única página ou até mesmo de páginas diferentes.
A 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 sem interrupções. 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.
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ção 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
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
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ê.
É 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
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) => {
// ...
});
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
epagereveal
no JavaScript. Para saber mais sobre transições de visualização para aplicativos com várias páginas, incluindo como configurar com a melhor performance com 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. 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 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 na superfície, 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.
Um menu suspenso consiste em 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 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 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.
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 no
z-index
. - Funcionalidade de dispensa leve: Clicar fora da área do pop-up vai fechá-lo e retornar 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ções padrão de componentes. : O navegador conecta semanticamente um popover ao gatilho.
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 popover. 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"
Animar efeitos de entrada e saída
Quando há pop-ups, é recomendável 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
.
A regra @starting-style
para animar os efeitos de entrada de display: none
e na camada superior.
A propriedade de sobreposição para controlar o comportamento da camada superior durante uma animação.
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 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, 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 ao posicionamento âncora agora está disponível a partir do Chrome 125.
Ao usar o posicionamento de âncoras, 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 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 posição 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, 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;
}
É 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 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âmicas 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, ao atingir a borda de uma janela de visualização com seu elemento ancorado, você também pode deixar o navegador lidar com a mudança de posicionamento para você.
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". 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, 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. 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);
}
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 de posição de â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
As experiências com tethering 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, no momento, popover
só funciona com botões como o elemento invocado 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 acionar um pop-up de um link e do usuário que mostra 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, 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 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 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 feliz em 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 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 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 ao vivo
selectedoption .text {
display: none;
}
Uma das maiores vantagens em reutilizar o elemento <select>
nessa 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.
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 a próxima seleção estilizável, tornando-a uma adição muito necessária à plataforma 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
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.
<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 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.
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 de componente útil 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. 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.
Demo Screencast
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 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
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. Muitas outras atualizações sobre qualidade de vida foram implementadas no último ano.
Aninhamento com olhar para frente
O aninhamento de CSS nativo foi lançado em todos os navegadores no ano passado e, desde então, foi aprimorado para oferecer suporte à antecipação, 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.
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. 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 uma div sem precisar aplicar o layout flex ou de grade e sem efeitos colaterais, como evitar o colapso da margem, que talvez você não queira desses algoritmos de layout.
Compatibilidade com navegadores
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
. 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
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
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.
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. 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 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
: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.
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()
.
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 eu não poderia 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.
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.
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.
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.
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
@property
E, finalmente, muito em breve, estamos animados para ver @property na linha de base. Esse é um recurso importante para fornecer significado semântico às propriedades personalizadas do CSS (também conhecidas como variáveis CSS) e ativar 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. 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 CSS.
Demo Screencast
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. 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 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, 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. Os recursos que precisávamos, mas que só sonávamos, agora estão finalmente se tornando realidade e 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 a seleção estilizável e nos conte o que achou. Estamos aqui para ouvir e ajudar.