Estado do CSS 2022

Recursos de estilização na Web atuais e futuros, como foram apresentados no Google I/O 2022, além de alguns extras.

O ano de 2022 está configurado para ser um dos melhores anos para o CSS, tanto em recursos quanto no lançamento cooperativo de recursos de navegador, com o objetivo colaborativo de implementar 14 recursos.

Visão geral

Esta postagem é o formato de artigo da palestra apresentada no Google I/O 2022. A ideia não é ser um guia aprofundado sobre cada recurso, mas uma introdução e uma breve visão geral para despertar seu interesse, oferecendo amplitude em vez de profundidade. Caso você tenha interesse, confira o final de uma seção para encontrar links de recursos com mais informações.

Índice

Use a lista abaixo para acessar os tópicos de interesse:

Compatibilidade com navegadores

Um dos principais motivos para que muitos recursos CSS sejam definidos para lançamento cooperativo é devido aos esforços da Interoperabilidade de 2022 (link em inglês). Antes de analisar os esforços do Interop, é importante analisar os esforços da Compat 2021.

Compatibilidade 2021

As metas para 2021, impulsionadas pelo feedback dos desenvolvedores via pesquisas, eram estabilizar os recursos atuais, melhorar o pacote de testes e aumentar as pontuações de aprovação dos navegadores para cinco recursos:

  1. Posicionamento de sticky
  2. Tamanho: aspect-ratio
  3. Layout do flex
  4. Layout do grid
  5. Posicionamento e animação de transform

As pontuações dos testes foram aumentadas em geral, demonstrando estabilidade e confiabilidade atualizadas. Parabéns às equipes!

Interoperabilidade de 2022

Este ano, os navegadores se reuniram para discutir os recursos e prioridades em que pretendiam trabalhar, unindo esforços. A empresa planejava oferecer os seguintes recursos da Web para desenvolvedores:

  1. @layer
  2. Espaços e funções de cor
  3. Contenção
  4. <dialog>
  5. Compatibilidade do formulário
  6. Rolagem
  7. Subgrade
  8. Tipografia
  9. Unidades da janela de visualização
  10. Compatibilidade com a Web

Mal posso esperar para ver esta lista emocionante e ambiciosa.

Novidades para 2022

Não surpreende que o estado do CSS 2022 seja drasticamente afetado pelo trabalho de Interoperabilidade de 2022.

Propagar camadas

Compatibilidade com navegadores

  • 99
  • 99
  • 97
  • 15,4

Origem

Antes de @layer, a ordem descoberta das folhas de estilo carregadas era muito importante, já que os estilos carregados por último podem substituir os estilos carregados anteriormente. Isso levou a folhas de estilo de entrada meticulosamente gerenciadas, em que os desenvolvedores precisavam carregar estilos menos importantes primeiro e estilos mais importantes depois. Há metodologias inteiras para ajudar os desenvolvedores a gerenciar essa importância, como o ITCSS.

Com @layer, o arquivo de entrada pode predefinir camadas e a ordem delas com antecedência. Em seguida, à medida que os estilos são carregados ou definidos, eles podem ser colocados em uma camada, permitindo a preservação da importância da substituição de estilo, mas sem a orquestração de carregamento meticulosamente gerenciada.

O vídeo mostra como as camadas em cascata definidas permitem um processo de criação e carregamento mais liberado e de estilo livre, mantendo a cascata conforme necessário.

O Chrome DevTools é útil para visualizar quais estilos estão vindo de quais camadas:

Captura de tela da barra lateral &quot;Estilos&quot; do Chrome Devtools, destacando como os estilos aparecem nos novos grupos de camadas.

Recursos

Subgrade

Compatibilidade com navegadores

  • 117
  • 117
  • 71
  • 16

Origem

Antes de subgrid, uma grade dentro de outra grade não podia se alinhar às células mãe ou às linhas de grade. Cada layout de grade era único. Muitos designers colocam uma única grade em todo o design e alinham constantemente itens nela, o que não pode ser feito em CSS.

Depois de subgrid, um filho de uma grade pode adotar as colunas ou linhas dos pais como próprias e alinhar a si mesmo ou aos filhos a elas.

Na demonstração a seguir, o elemento "body" cria uma grade clássica de três colunas: a coluna do meio é chamada de main, e as colunas da esquerda e da direita nomeam as linhas fullbleed. Em seguida, cada elemento no corpo, <nav> e <main>, adota as linhas nomeadas do corpo definindo grid-template-columns: subgrid.

​​body {
  display: grid;
  grid-template-columns:
    [fullbleed-start]
    auto [main-start] min(90%, 60ch) [main-end] auto
    [fullbleed-end]
  ;
}

body > * {
  display: grid;
  grid-template-columns: subgrid;
}

Por fim, os filhos de <nav> ou <main> podem se alinhar ou dimensionar a si mesmos usando as colunas e linhas fullbleed e main.

.main-content {
  grid-column: main;
}

.fullbleed {
  grid-column: fullbleed;
}

O Devtools pode ajudar você a ver as linhas e as subgrades (apenas no Firefox no momento). Na imagem a seguir, a grade e as subgrades mãe foram sobrepostas. Agora, ele lembra como os designers estavam pensando sobre o layout.

Captura de tela de uma demonstração de subgrade usando as ferramentas de sobreposição de grade do Chrome Devtools para mostrar as linhas definidas pelo CSS.

No painel de elementos do DevTools, você pode ver quais elementos são grades e subgrades, o que é muito útil para depurar ou validar o layout.

Captura de tela do painel Elements do Chrome Devtools, rotulando quais elementos têm layouts de grade ou subgrade.
Captura de tela do Firefox Devtools

Recursos

Consultas em contêiner

Compatibilidade com navegadores

  • 105
  • 105
  • 110
  • 16

Origem

Antes de @container, os elementos de uma página da Web só podiam responder ao tamanho da janela de visualização inteira. Isso é ótimo para layouts macro. No entanto, para microlayouts, em que o contêiner externo não é a janela de visualização inteira, é impossível que o layout se ajuste corretamente.

Depois de @container, os elementos podem responder a um tamanho ou estilo de contêiner pai. A única ressalva é que os contêineres precisam se declarar como possíveis destinos de consulta, o que é um pequeno requisito para um grande benefício.

/* establish a container */
.day {
  container-type: inline-size;
  container-name: calendar-day;
}

Esses estilos são o que faz com que as colunas Seg, Ter, Qua, Qui e Sex do vídeo a seguir possam ser consultadas pelos elementos de evento.

Demonstração por Una Kravets

Este é o CSS para consultar o tamanho do contêiner calendar-day e ajustar um layout e tamanhos de fonte:

@container calendar-day (max-width: 200px) {
  .date {
    display: block;
  }

  .date-num {
    font-size: 2.5rem;
    display: block;
  }
}

Veja outro exemplo: um componente de livro se adapta ao espaço disponível na coluna para a qual ele é arrastado:

Demonstração por Max Böck

Una está correto ao avaliar a situação como o novo responsivo. Há muitas decisões de design interessantes e significativas a serem tomadas ao usar @container.

Recursos

accent-color

Compatibilidade com navegadores

  • 93
  • 93
  • 92
  • 15,4

Origem

Antes de accent-color, quando você queria um formulário com cores correspondentes à marca, podia acabar com bibliotecas complexas ou soluções CSS que se tornavam difíceis de gerenciar ao longo do tempo. Embora eles ofereçam todas as opções e, esperamos, incluem a acessibilidade, a escolha de usar os componentes integrados ou adotar os seus se torna tedioso continuar escolhendo.

Depois de accent-color, uma linha de CSS traz uma cor da marca para os componentes integrados. Além de uma tonalidade, o navegador escolhe de maneira inteligente as cores de contraste adequadas para as partes complementares do componente e se adapta aos esquemas de cores do sistema (claro ou escuro).

/* tint everything */
:root {
  accent-color: hotpink;
}

/* tint one element */
progress {
  accent-color: indigo;
}

Elementos HTML com acento claro e escuro lado a lado para comparação.

Para saber mais sobre accent-color, consulte minha postagem no web.dev (link em inglês), em que explico muitos outros aspectos dessa propriedade CSS útil.

Recursos

Nível de cores 4 e 5

A Web é dominada por sRGB nas últimas décadas, mas em um mundo digital em expansão de telas de alta definição e dispositivos móveis pré-equipados com telas OLED ou QLED, sRGB não é suficiente. Além disso, páginas dinâmicas que se adaptam às preferências do usuário são esperadas, e o gerenciamento de cores tem sido uma preocupação crescente para designers, sistemas de design e mantenedores de código.

No entanto, não em 2022. O CSS tem várias novas funções de cor e espaços: - Cores que alcançam os recursos de cor de alta definição das telas. - Espaços de cor que correspondem a uma intent, como uniformidade perceptível. - Espaços de cores para gradientes que alteram drasticamente os resultados de interpolação. - funções de cor para ajudar você a misturar e contrastar e escolher em qual espaço você fará o trabalho.

Antes de todas essas características de cores, os sistemas de design precisavam pré-calcular as cores de contraste adequadas e garantir paletas vibrantes, tudo isso enquanto os pré-processadores ou o JavaScript faziam o trabalho pesado.

Depois de todos esses recursos de cores, o navegador e o CSS podem fazer todo o trabalho dinamicamente e no momento certo. Em vez de enviar muitos KBs de CSS e JavaScript aos usuários para ativar temas e cores de visualização de dados, o CSS pode fazer a orquestração e os cálculos. O CSS também é mais bem equipado para verificar o suporte antes do uso ou lidar com os substitutos sem problemas.

@media (dynamic-range: high) {
  .neon-pink {
    --neon-glow: color(display-p3 1 0 1);
  }
}

@supports (color: lab(0% 0 0)) {
  .neon-pink {
    --neon-glow: lab(150% 160 0);
  }
}

hwb()

Compatibilidade com navegadores

  • 101
  • 101
  • 96
  • 15

Origem

HWB significa matiz, branco e escuridão. Ela se apresenta como uma maneira correta de articular cores, já que é apenas uma tonalidade e uma quantidade de branco ou preto para clarear ou escurecer. Artistas que misturam cores com branco ou preto podem gostar dessa adição de sintaxe de cor.

O uso dessa função de cor resulta em cores do espaço de cores sRGB, da mesma forma que HSL e RGB. Em termos de novidades para 2022, isso não oferece novas cores, mas pode facilitar algumas tarefas para os fãs de sintaxe e modelo mental.

Recursos

Espaços de cor

A forma como as cores são representadas é feita com um espaço de cor. Cada espaço de cores oferece vários recursos e compensações para trabalhar com cores. Alguns podem agrupar todas as cores brilhantes, outros podem alinhá-las primeiro com base na luminosidade.

Em 2022, o CSS vai oferecer 10 novos espaços de cores, cada um com recursos exclusivos para ajudar designers e desenvolvedores a exibir, escolher e misturar cores. Anteriormente, sRGB era a única opção para trabalhar com cores, mas agora o CSS libera um novo potencial e um novo espaço de cores padrão, o LCH.

color-mix()

Compatibilidade com navegadores

  • 111
  • 111
  • 113
  • 16,2

Origem

Antes de color-mix(), desenvolvedores e designers precisavam de pré-processadores como o Sass (link em inglês) para misturar as cores antes que o navegador as visse. A maioria das funções de mistura de cores também não oferecia a opção de especificar em qual espaço de cores fazer a mistura, às vezes, resultando em resultados confusos.

Depois de color-mix(), os desenvolvedores e designers podem misturar cores no navegador, junto com todos os outros estilos, sem executar processos de build ou incluir JavaScript. Além disso, eles podem especificar em qual espaço de cor fazer a mistura ou usar o espaço de cores de mistura padrão de LCH.

Muitas vezes, uma cor da marca é usada como base, e variantes são criadas com ela, como cores mais claras ou mais escuras para estilos de passar cursor. Veja como isso fica com color-mix():

.color-mix-example {
  --brand: #0af;

  --darker: color-mix(var(--brand) 25%, black);
  --lighter: color-mix(var(--brand) 25%, white);
}

Se você quiser misturar essas cores em um espaço de cores diferente, como srgb, mude-o:

.color-mix-example {
  --brand: #0af;

  --darker: color-mix(in srgb, var(--brand) 25%, black);
  --lighter: color-mix(in srgb, var(--brand) 25%, white);
}

Veja a seguir uma demonstração de temas usando color-mix(). Tente mudar a cor da marca e observe a atualização do tema:

Aproveite a mistura de cores em vários espaços de cores nas suas folhas de estilo em 2022!

Recursos

color-contrast()

Compatibilidade com navegadores

  • x
  • x
  • x

Origem

Antes de color-contrast(), os autores da folha de estilo precisavam saber com antecedência as cores acessíveis. Muitas vezes, uma paleta mostra texto em preto ou branco em uma amostra de cor para indicar ao usuário do sistema de cores qual cor do texto seria necessária para contrastar adequadamente essa amostra.

Captura de tela de três paletas do Material Design, mostrando 14 cores e as cores de contraste branca ou preta apropriadas para o texto.
Exemplo das paletas de cores do Material Design de 2014

Após color-contrast(), os autores da folha de estilo podem descarregar a tarefa inteiramente no navegador. É possível usar o navegador para selecionar automaticamente uma cor preta ou branca, além de fornecer uma lista de cores adequadas ao sistema de design e fazer com que ele escolha a primeira para transmitir a taxa de contraste desejada.

Esta é uma captura de tela de uma demonstração do conjunto da paleta de cores HWB em que as cores do texto são escolhidas automaticamente pelo navegador com base na cor da amostra:

Captura de tela da demonstração da HWB, em que cada paleta tem um par diferente de texto claro ou escuro, conforme determinado pelo navegador.
Teste a demonstração

Os princípios básicos da sintaxe têm esta aparência, em que cinza é transmitido para a função e o navegador determina se preto ou branco têm mais contraste:

color: color-contrast(gray);

A função também pode ser personalizada com uma lista de cores, na qual ela vai escolher a cor de maior contraste na seleção:

color: color-contrast(gray vs indigo, rebeccapurple, hotpink);

Por fim, caso seja preferível não escolher a cor de maior contraste da lista, é possível fornecer uma taxa de contraste desejada e escolher a primeira cor a ser transmitida:

color: color-contrast(
  var(--bg-blue-1)
  vs
  var(--text-lightest), var(--text-light), var(--text-subdued)
  to AA /* 4.5 could also be passed */
);

Essa função pode ser usada para outras situações além da cor do texto, mas estimamos que esse será o caso de uso principal. Pense em como será mais fácil oferecer interfaces acessíveis e legíveis quando a escolha das cores contrastantes adequadas é integrada à própria linguagem CSS.

Recursos

Sintaxe de cor relativa

Compatibilidade com navegadores

  • 111
  • 111
  • 113
  • 15

Origem

Antes da sintaxe de cor relativa, para calcular a cor e fazer ajustes, os canais de cores precisavam ser colocados individualmente nas propriedades personalizadas. Essa limitação também tornou a HSL a função de cor principal para manipular cores, já que a matiz, a saturação ou o brilho podiam ser ajustados de maneira direta com calc().

Depois da sintaxe de cor relativa, qualquer cor em qualquer espaço pode ser desconstruída, modificada e retornada como uma cor, tudo em uma linha do CSS. Não há mais limitações ao HSL. As manipulações podem ser feitas em qualquer espaço de cor desejado, e muito menos propriedades personalizadas precisam ser criadas para facilitar isso.

No exemplo de sintaxe a seguir, um hexadecimal base é fornecido e duas novas cores são criadas em relação a ele. A primeira cor --absolute-change cria uma nova cor em LCH a partir da cor de base e, em seguida, substitui o brilho da cor de base por 75%, mantendo o chroma (c) e a matiz (h). A segunda cor --relative-change cria uma nova cor em LCH a partir da cor de base, mas desta vez reduz o chroma (c) em 20%.

.relative-color-syntax {
  --color: #0af;
  --absolute-change: lch(from var(--color) 75% c h);
  --relative-change: lch(from var(--color) l calc(c-20%) h);
}

Isso é parecido com misturar cores, mas é mais semelhante a alterações do que mistura. Você pode transmitir uma cor de outra cor e ter acesso aos três valores de canal, nomeados pela função de cor usada, com a oportunidade de ajustar esses canais. Resumindo, essa é uma sintaxe muito legal e poderosa para cor.

Na demonstração a seguir, usei a sintaxe de cor relativa para criar variantes mais claras e escuras de uma cor base e usei color-contrast() para garantir que os rótulos tenham o contraste adequado:

Captura de tela com três colunas, cada uma em que cada coluna é mais escura ou mais clara do que a coluna central.
Teste a demonstração

Essa função também pode ser usada para gerar a paleta de cores. Confira uma demonstração em que paletas inteiras são geradas com base em uma cor de base. Esse conjunto de CSS alimenta todas as várias paletas. Cada paleta fornece uma base diferente. Como bônus, já usei o LCH, e veja como as paletas são perceptíveis. Não há pontos quentes ou mortos para serem vistos, graças a esse espaço de cores.

:root {
  --_color-base: #339af0;

  --color-0:  lch(from var(--_color-base) 98% 10 h);
  --color-1:  lch(from var(--_color-base) 93% 20 h);
  --color-2:  lch(from var(--_color-base) 85% 40 h);
  --color-3:  lch(from var(--_color-base) 75% 46 h);
  --color-4:  lch(from var(--_color-base) 66% 51 h);
  --color-5:  lch(from var(--_color-base) 61% 52 h);
  --color-6:  lch(from var(--_color-base) 55% 57 h);
  --color-7:  lch(from var(--_color-base) 49% 58 h);
  --color-8:  lch(from var(--_color-base) 43% 55 h);
  --color-9:  lch(from var(--_color-base) 39% 52 h);
  --color-10: lch(from var(--_color-base) 32% 48 h);
  --color-11: lch(from var(--_color-base) 25% 45 h);
  --color-12: lch(from var(--_color-base) 17% 40 h);
  --color-13: lch(from var(--_color-base) 10% 30 h);
  --color-14: lch(from var(--_color-base) 5% 20 h);
  --color-15: lch(from var(--_color-base) 1% 5 h);
}
Captura de tela de 15 paletas geradas dinamicamente pelo CSS.
Confira a demonstração

Esperamos que agora você já possa ver como os espaços de cor e as diferentes funções de cor podem ser usados para diferentes propósitos, com base nos pontos fortes e fracos deles.

Recursos

Espaços de cor gradiente

Antes dos espaços de cores gradientes, sRGB era o espaço de cores padrão usado. sRGB geralmente é confiável, mas tem alguns pontos fracos, como a zona sem saída cinza (link em inglês).

4 gradientes em uma grade, todos de ciano a rosa profundo. LCH e LAB têm uma vitalidade mais consistente, e sRGB fica um pouco dessaturada no meio.

Após os espaços de cor gradiente, informe ao navegador qual espaço de cores usar para a interpolação de cores. Isso dá aos desenvolvedores e designers a capacidade de escolher o gradiente que preferem. O espaço de cores padrão também muda para LCH em vez de sRGB.

A adição de sintaxe vem após a direção do gradiente, usa a nova sintaxe in e é opcional:

background-image: linear-gradient(
  to right in hsl,
  black, white
);

background-image: linear-gradient(
  to right in lch,
  black, white
);

Veja aqui um gradiente básico e essencial de preto para branco. Veja a faixa de resultados em cada espaço de cor. Alguns alcançam o preto escuro mais cedo do que outros, alguns se tornam brancos tarde demais.

11 espaços de cor mostrados comparando preto e branco.

No próximo exemplo, o preto é transferido para o azul porque é um espaço problemático conhecido para gradientes. A maioria dos espaços de cor se transforma em roxo durante a interpolação de cores ou, como gosto de pensar nisso, à medida que as cores transitam dentro do espaço de cores do ponto A ao ponto B. Como o gradiente pega uma linha reta do ponto A ao ponto B, a forma do espaço de cores muda drasticamente as paradas que o caminho percorre ao longo do caminho.

11 espaços de cor mostrados comparando azul e preto.

Para acessar mais análises detalhadas, exemplos e comentários, leia esta conversa no Twitter (em inglês).

Recursos

inert

Compatibilidade com navegadores

  • 102
  • 102
  • 112
  • 15.5

Origem

Antes de inert, era uma prática recomendada orientar o foco do usuário para áreas da página ou do app que precisavam de atenção imediata. Essa estratégia de foco guiado ficou conhecida como captura de foco porque os desenvolvedores colocavam o foco em um espaço interativo, detectavam eventos de mudança de foco e, quando o foco deixava o espaço interativo, era forçado a entrar novamente. Os usuários de teclados ou leitores de tela são direcionados de volta ao espaço interativo para garantir que a tarefa seja concluída antes de avançar.

Depois de inert, nenhuma armadilha é necessária, porque você pode congelar ou proteger seções inteiras da página ou do app. Cliques e tentativas de mudança de foco simplesmente não estão disponíveis enquanto essas partes de um documento estão inertes. Também é possível pensar nisso como guardas em vez de uma armadilha, em que inert não tem interesse em fazer você ficar em algum lugar, mas deixar outros locais indisponíveis.

Um bom exemplo é a função JavaScript alert():

O site é mostrado como interativo, um alert() é chamado e a página não está mais ativa.

Observe no vídeo anterior como a página ficou acessível por mouse e teclado até que um alert() fosse chamado. Depois que a caixa de diálogo de alerta pop-up foi mostrada, o restante da página foi congelado, ou inert. O foco do usuário é colocado na caixa de diálogo de alerta e não tem outro lugar para ir. Depois que o usuário interage e conclui a solicitação da função de alerta, a página fica interativa novamente. O inert capacita os desenvolvedores a ter essa mesma experiência de foco guiado com facilidade.

Este é um pequeno exemplo de código que mostra como funciona:

<body>
  <div class="modal">
    <h2>Modal Title</h2>
    <p>...<p>
    <button>Save</button>
    <button>Discard</button>
  </div>
  <main inert>
    <!-- cannot be keyboard focused or clicked -->
  </main>
</body>

Uma caixa de diálogo é um ótimo exemplo, mas inert também é útil para aspectos como a experiência do usuário do menu lateral deslizante. Quando um usuário desliza para fora do menu lateral, não é permitido que o mouse ou o teclado interajam com a página por trás dele, porque isso é um pouco complicado para os usuários. Em vez disso, quando o menu lateral estiver aparecendo, torne a página inerte. Agora os usuários precisam fechar ou navegar nesse menu, sem se perder em outro lugar da página com um menu aberto.

Recursos

Fontes COLRv1

Antes das fontes COLRv1, a Web tinha fontes OT-SVG, também um formato aberto para fontes com gradientes, cores e efeitos integrados. No entanto, elas podiam crescer muito e, embora permitissem a edição do texto, não havia muito escopo para personalização.

Depois das fontes COLRv1, a Web tem menor consumo, escalonável em vetores, reposicional, com gradiente e recursos de modo de combinação, que aceitam parâmetros para personalizar a fonte por caso de uso ou de acordo com uma marca.

Visualização de comparação e gráfico de barras mostrando como as fontes COLRv1 são mais nítidas e menores.
Imagem de https://developer.chrome.com/blog/colrv1-fonts/

Confira um exemplo de uma postagem do Blog de desenvolvedores Chrome sobre emojis. Talvez você tenha notado que, se você aumentar o tamanho da fonte em um emoji, ele não ficará nítido. É uma imagem, e não uma arte vetorial. Muitas vezes, quando um emoji é usado, ele é trocado por um recurso de maior qualidade. Com as fontes COLRv1, os emojis são vetores e bonitos:

As fontes de ícones podem fazer coisas incríveis com esse formato, oferecendo paletas de cores duplas personalizadas e muito mais. Carregar uma fonte COLRv1 é como qualquer outro arquivo de fonte:

@import url(https://fonts.googleapis.com/css2?family=Bungee+Spice);

A personalização da fonte COLRv1 é feita com @font-palette-values, um CSS especial para agrupar e nomear um conjunto de opções de personalização em um pacote para referência futura. Observe como um nome personalizado é especificado, assim como uma propriedade personalizada, começando com --:

@import url(https://fonts.googleapis.com/css2?family=Bungee+Spice);

@font-palette-values --colorized {
  font-family: "Bungee Spice";
  base-palette: 0;
  override-colors: 0 hotpink, 1 cyan, 2 white;
}

Com --colorized como um alias para as personalizações, a última etapa é aplicar a paleta a um elemento que esteja usando a família de fontes de cores:

@import url(https://fonts.googleapis.com/css2?family=Bungee+Spice);

@font-palette-values --colorized {
  font-family: "Bungee Spice";
  base-palette: 0;
  override-colors: 0 hotpink, 1 cyan, 2 white;
}

.spicy {
  font-family: "Bungee Spice";
  font-palette: --colorized;
}
Captura de tela da fonte Bungee Spice com a palavra DUNE.
Fonte Bungee Spice mostrada com cores personalizadas, fonte de https://developer.chrome.com/blog/colrv1-fonts/

Com cada vez mais fontes variáveis e de cores sendo disponibilizadas, a tipografia da Web está em um caminho magnífico em direção à personalização avançada e à expressão criativa.

Recursos

Unidades da janela de visualização

Gráfico mostrando como a tela do dispositivo, a janela do navegador e um iframe têm janelas de visualização diferentes.

Antes das novas variantes da janela de visualização, a Web oferecia unidades físicas para ajudar no ajuste delas. Havia um para altura, largura, menor tamanho (vmin) e maior lado (vmax). Isso funcionou bem para muitas coisas, mas os navegadores para dispositivos móveis apresentavam uma complexidade.

Em dispositivos móveis, ao carregar uma página, a barra de status com o URL é exibida, e ela ocupa parte do espaço da janela de visualização. Depois de alguns segundos e um pouco de interatividade, a barra de status pode desaparecer para permitir uma experiência melhor da janela de visualização. No entanto, quando essa barra desliza para fora, a altura da janela de visualização muda, e todas as unidades de vh são deslocadas e redimensionadas conforme o tamanho de destino muda. Nos últimos anos, a unidade vh precisava decidir especificamente qual dos dois tamanhos da janela de visualização seria usado, porque isso estava causando problemas de layout visual desagradáveis em dispositivos móveis. Foi determinado que vh sempre representaria a maior janela de visualização.

.original-viewport-units {
  height: 100vh;
  width: 100vw;
  --size: 100vmin;
  --size: 100vmax;
}

Depois que as novas variantes da janela de visualização, as unidades pequenas, grandes e dinâmicas da janela de visualização serão disponibilizadas, com a adição de equivalentes lógicos aos físicos. A ideia é oferecer aos desenvolvedores e designers a capacidade de escolher qual unidade querem usar no cenário em questão. Talvez não haja problema em fazer uma pequena mudança de layout desagradável quando a barra de status desaparece. Então, a dvh (altura dinâmica da janela de visualização) pode ser usada sem problemas.

Uma imagem com três smartphones para ajudar a ilustrar o VD, a LVL e a SVH. O smartphone de exemplo de DVH
   tem duas linhas verticais, uma entre a parte de baixo da barra de pesquisa
   e a parte de baixo da janela de visualização, e outra entre a parte de cima da barra de pesquisa (abaixo da
   barra de status do sistema) até a parte de baixo da janela de visualização, mostrando como o DVH pode ter um
   desses dois tamanhos. A LVH é mostrada no meio, com uma linha entre a
   parte inferior da barra de status do dispositivo e o botão da janela de visualização do smartphone. O último é o exemplo de unidade SVH, que mostra uma linha da parte inferior da barra de pesquisa do navegador até a parte inferior da janela de visualização.

Confira uma lista completa com todas as novas opções de unidade da janela de visualização disponibilizadas com as novas variantes da janela de visualização:

Unidades de altura da janela de visualização
​​.new-height-viewport-units {
  height: 100vh;
  height: 100dvh;
  height: 100svh;
  height: 100lvh;
  block-size: 100vb;
  block-size: 100dvb;
  block-size: 100svb;
  block-size: 100lvb;
}
Unidades da janela de visualização de largura
.new-width-viewport-units {
  width: 100vw;
  width: 100dvw;
  width: 100svw;
  width: 100lvw;
  inline-size: 100vi;
  inline-size: 100dvi;
  inline-size: 100svi;
  inline-size: 100lvi;
}
Menor unidade lateral da janela de visualização
.new-min-viewport-units {
  --size: 100vmin;
  --size: 100dvmin;
  --size: 100svmin;
  --size: 100lvmin;
}
Maiores unidades laterais da janela de visualização
.new-max-viewport-units {
  --size: 100vmax;
  --size: 100dvmax;
  --size: 100svmax;
  --size: 100lvmax;
}

Esperamos que isso dê aos desenvolvedores e designers a flexibilidade necessária para criar designs responsivos na janela de visualização.

Recursos

:has()

Compatibilidade com navegadores

  • 105
  • 105
  • 121
  • 15,4

Origem

Antes de :has(), o assunto de um seletor estava sempre no final. Por exemplo, o assunto desse seletor é um item da lista: ul > li. Os pseudosseletores podem alterá-lo, mas não alteram o assunto: ul > li:hover ou ul > li:not(.selected).

Depois de :has(), um assunto mais alto na árvore de elementos pode permanecer como assunto ao fornecer uma consulta sobre filhos: ul:has(> li). É fácil entender como :has() recebeu o nome comum de "seletor pai", já que o assunto do seletor agora é o pai nesse caso.

Este é um exemplo de sintaxe básica em que a classe .parent permanece como assunto, mas só é selecionada se um elemento filho tiver a classe .child:

.parent:has(.child) {...}

Confira um exemplo em que um elemento <section> é o assunto, mas o seletor só faz a correspondência se um dos filhos tiver :focus-visible:

section:has(*:focus-visible) {...}

O seletor :has() começa a se tornar um utilitário fantástico quando casos de uso mais práticos se tornam aparentes. Por exemplo, no momento, não é possível selecionar tags <a> ao unir imagens. Isso dificulta ensinar à tag âncora como mudar os estilos nesse caso de uso. Isso é possível com :has():

a:has(> img) {...}

Esses foram exemplos em que :has() se parece apenas com um seletor pai. Considere o caso de uso de imagens dentro de elementos <figure> e ajuste de estilos nas imagens se a figura tiver um <figcaption>. No exemplo a seguir, as figuras com CMEKs são selecionadas e, em seguida, as imagens dentro desse contexto. O :has() é usado sem mudar o assunto, já que o assunto são imagens, não figuras:

figure:has(figcaption) img {...}

As combinações são aparentemente infinitas. Combine :has() com consultas de quantidade e ajuste os layouts de grade CSS com base no número de filhos. Combine :has() com estados de pseudoclasse interativos e crie aplicativos que respondam de novas maneiras criativas.

A verificação de suporte é simplificada com @supports e a função selector(), que testa se o navegador entende a sintaxe antes de usá-lo:

@supports (selector(:has(works))) {
  /* safe to use :has() */
}

Recursos

2022 em diante

Ainda haverá várias coisas difíceis de realizar depois que todos esses recursos incríveis forem lançados, em 2022. Na próxima seção, você verá alguns dos problemas restantes e as soluções que estão sendo desenvolvidas ativamente para resolvê-los. Essas soluções são experimentais, mesmo que possam estar especificadas ou disponíveis atrás de sinalizações nos navegadores.

O resultado das próximas seções deve ser confiante de que os problemas listados têm muitas pessoas de muitas empresas em busca de resolução, e não que essas soluções serão lançadas em 2023.

Propriedades personalizadas com baixa digitação

Compatibilidade com navegadores

  • 85
  • 85
  • 16.4

Origem

As propriedades personalizadas do CSS são incríveis. Eles permitem que todos os tipos de coisas sejam armazenados dentro de uma variável nomeada, que pode ser estendida, calculada, compartilhada e muito mais. Na verdade, eles são tão flexíveis que seria bom ter alguns menos flexíveis.

Considere um cenário em que uma box-shadow usa propriedades personalizadas para os valores:

box-shadow: var(--x) var(--y) var(--blur) var(--spread) var(--color);

Tudo isso funciona bem até que qualquer uma das propriedades seja alterada para um valor que o CSS não aceite, como --x: red. Toda a sombra quebra se alguma das variáveis aninhadas estiver ausente ou estiver definida como um tipo de valor inválido.

É aí que entra a @property: --x pode se tornar uma propriedade personalizada tipada, que não é mais flexível e flexível, mas segura com alguns limites definidos:

@property --x {
  syntax: '<length>';
  initial-value: 0px;
  inherits: false;
}

Agora, quando o box-shadow usar var(--x) e depois uma tentativa de --x: red for feita, o red vai ser ignorado, já que não é um <length>. Isso significa que a sombra continua funcionando, mesmo que um valor inválido tenha sido atribuído a uma das propriedades personalizadas. Em vez de falhar, ele reverte para o initial-value de 0px.

Animação

Além da segurança de tipos, ela também abre muitas portas para animação. A flexibilidade da sintaxe CSS impossibilita a animação de algumas coisas, como gradientes. O @property é útil aqui, porque a propriedade de CSS digitada pode informar o navegador sobre a intenção do desenvolvedor dentro de uma interpolação excessivamente complexa. Essencialmente, ela limita o escopo de possibilidade, de modo que um navegador possa animar aspectos de um estilo que antes não conseguia.

Considere este exemplo de demonstração, em que um gradiente radial é usado para fazer uma parte de uma sobreposição, criando um efeito de foco de destaque. O JavaScript define o "x" e o "y" do mouse quando a tecla alt/opt é pressionada e muda o tamanho focal para um valor menor, como 25%, criando o círculo de foco de destaque na posição do mouse:

Teste a demonstração
.focus-effect {
  --focal-size: 100%;
  --mouse-x: center;
  --mouse-y: center;

  mask-image: radial-gradient(
    circle at var(--mouse-x) var(--mouse-y),
    transparent 0%,
    transparent var(--focal-size),
    black 0%
  );
}

No entanto, os gradientes não podem ser animados. Eles são muito flexíveis e complexos para o navegador "simplesmente derivar" como você deseja que eles sejam animados. No entanto, com @property, uma propriedade pode ser digitada e animada de forma isolada, permitindo que o navegador entenda facilmente a intent.

Videogames que usam esse efeito de foco sempre animam o círculo, de um círculo grande para um círculo. Confira como usar @property na nossa demonstração para que o navegador anime a máscara de gradiente:

@property --focal-size {
  syntax: '<length-percentage>';
  initial-value: 100%;
  inherits: false;
}

.focus-effect {
  --focal-size: 100%;
  --mouse-x: center;
  --mouse-y: center;

  mask-image: radial-gradient(
    circle at var(--mouse-x) var(--mouse-y),
    transparent 0%,
    transparent var(--focal-size),
    black 0%
  );

  transition: --focal-size .3s ease;
}
Confira a demonstração

O navegador agora pode animar o tamanho do gradiente porque reduzimos a área de superfície da modificação a apenas uma propriedade e digitamos o valor para que o navegador possa interpolar os comprimentos de maneira inteligente.

O @property pode fazer muito mais, mas essas pequenas ativações podem ajudar muito.

Recursos

Esteve em min-width ou max-width

Antes dos intervalos de consulta de mídia, uma consulta de mídia CSS usa min-width e max-width para articular as condições. Ela pode ter esta aparência:

@media (min-width: 320px) {
  …
}

Após os intervalos das consultas de mídia, a mesma consulta de mídia teria esta aparência:

@media (width >= 320px) {
  …
}

Uma consulta de mídia CSS usando min-width e max-width pode ter esta aparência:

@media (min-width: 320px) and (max-width: 1280px) {
  …
}

Após os intervalos das consultas de mídia, a mesma consulta de mídia teria esta aparência:

@media (320px <= width <= 1280px) {
  …
}

Dependendo do seu conhecimento em programação, um desses métodos parecerá muito mais legível que o outro. Graças às especificações adicionadas, os desenvolvedores poderão escolher qual a melhor opção ou até mesmo usá-las de forma intercambiável.

Recursos

Nenhuma variável de consulta de mídia

Antes de @custom-media, as consultas de mídia precisavam se repetir várias vezes ou depender de pré-processadores para gerar a saída adequada com base em variáveis estáticas durante o tempo de build.

Depois de @custom-media, o CSS permite a atribuição de alias a consultas de mídia e a referência delas, assim como em uma propriedade personalizada.

Nomear itens é muito importante: ele pode alinhar o propósito com a sintaxe, facilitando o compartilhamento e o uso em equipes. Aqui estão algumas consultas de mídia personalizadas que me seguem entre projetos:

@custom-media --OSdark  (prefers-color-scheme: dark);
@custom-media --OSlight (prefers-color-scheme: light);

@custom-media --pointer (hover) and (pointer: coarse);
@custom-media --mouse   (hover) and (pointer: fine);

@custom-media --xxs-and-above (width >= 240px);
@custom-media --xxs-and-below (width <= 240px);

Agora que estão definidos, posso usar um deles assim:

@media (--OSdark) {
  :root {
    …
  }
}

Encontre uma lista completa de consultas de mídia personalizadas que eu uso na minha biblioteca de propriedades personalizadas do CSS Open Props.

Recursos

É muito bom aninhar seletores

Antes de @nest, havia muita repetição nas folhas de estilo. Ele se tornou especialmente difícil de administrar quando os seletores eram longos e cada um visava pequenas diferenças. A conveniência do aninhamento é um dos motivos mais comuns para adotar um pré-processador.

Depois de @nest, a repetição desaparece. Quase todos os recursos de aninhamento ativado para pré-processador serão disponibilizados integrados ao CSS.

article {
  color: darkgray;
}

article > a {
  color: var(--link-color);
}

/* with @nest becomes */

article {
  color: darkgray;

  & > a {
    color: var(--link-color);
  }
}

Para mim, o que é mais importante sobre o aninhamento, além de não repetir article no seletor aninhado, é que o contexto de estilo permanece em um bloco de estilo. Em vez de pular de um seletor e seus estilos para outro com estilos (exemplo 1), o leitor pode permanecer no contexto de um artigo e conferir que o artigo tem links dentro dele. A relação e a intent de estilo são agrupadas, para que article pareça ser proprietário dos próprios estilos.

A propriedade também pode ser considerada como centralização. Em vez de procurar estilos relevantes em uma folha de estilo, todos eles podem ser encontrados aninhados em um contexto. Isso funciona com relações pai para filho, mas também com relações pai para pai.

Considere um componente filho que quer se ajustar quando em um contexto pai diferente, em vez de o pai ser proprietário do estilo e mudar um filho:

/* parent owns this, adjusting children */
section:focus-within > article {
  border: 1px solid hotpink;
}

/* with @nest becomes */

/* article owns this, adjusting itself when inside a section:focus-within */
article {
  @nest section:focus-within > & {
     border: 1px solid hotpink;
  }
}

De modo geral, o @nest ajuda na organização, centralização e propriedade de estilo mais saudáveis. Os componentes podem agrupar e ter os próprios estilos, em vez de distribuí-los entre outros blocos de estilo. Pode parecer pequeno nesses exemplos, mas pode ter impactos muito grandes por conveniência e legibilidade.

Recursos

Definir o escopo dos estilos é muito difícil

Compatibilidade com navegadores

  • 118
  • 118
  • x
  • 17,4

Antes de @scope, muitas estratégias existiam porque os estilos em CSS são propagados, herdam e têm escopo global por padrão. Esses recursos do CSS são muito convenientes para muitas coisas, mas para sites e aplicativos complexos, com possivelmente muitos estilos diferentes de componentes, o espaço global e a natureza da cascata podem fazer com que os estilos pareçam estar vazando.

Após @scope, não é possível definir o escopo dos estilos apenas em um contexto, como uma classe, mas também articular onde os estilos terminam e não continuar em cascata ou herdar.

No exemplo a seguir, o escopo da convenção de nomenclatura BEM pode ser revertido para a intent real. O seletor de BEM está tentando definir o escopo da cor de um elemento header para um contêiner .card com convenções de nomenclatura. Isso exige que o cabeçalho tenha esse nome de classe, concluindo a meta. Com @scope, nenhuma convenção de nomenclatura é necessária para concluir a mesma meta sem marcar o elemento de cabeçalho:

.card__header {
  color: var(--text);
}

/* with @scope becomes */

@scope (.card) {
  header {
    color: var(--text);
  }
}

Confira outro exemplo, menos específico de componente e mais sobre a natureza de escopo global do CSS. Temas escuros e claros precisam coexistir em uma folha de estilo, em que a ordem é importante para determinar um estilo vencedor. Normalmente, isso significa que os estilos de tema escuro vêm depois do tema claro, estabelecendo claro como padrão e escuro como opcional. Evite a ordenação e a disputa de escopo com @scope:

​​@scope (.light-theme) {
  a { color: purple; }
}

@scope (.dark-theme) {
  a { color: plum; }
}

Para completar a história aqui, o @scope também permite estabelecer onde termina o escopo do estilo. Isso não pode ser feito com nenhuma convenção de nomenclatura ou pré-processador. Isso é especial e somente algo que o CSS integrado ao navegador pode fazer. No exemplo a seguir, os estilos img e .content são aplicados exclusivamente quando um filho de uma .media-block é irmão ou pai de .content:

@scope (.media-block) to (.content) {
  img {
    border-radius: 50%;
  }

  .content {
    padding: 1em;
  }
}

Recursos

Não há maneira CSS para um layout de alvenaria

Antes da alvenaria CSS com grade, o JavaScript era a melhor maneira de criar um layout de alvenaria, já que qualquer um dos métodos CSS com colunas ou flexbox representava de maneira imprecisa a ordem do conteúdo.

Após a alvenaria CSS com grade, nenhuma biblioteca JavaScript será necessária, e a ordem do conteúdo será correta.

Captura de tela do layout de alvenaria que mostra números passando por cima e depois descendo.
Imagem e demonstração da Smashing Magazine
https://www.smashingmagazine.com/native-css-masonry-layout-css-grid/

A demonstração anterior é realizada com o seguinte CSS:

.container {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: masonry;
}

É bom saber que essa estratégia está faltando, e você pode fazer um teste hoje mesmo no Firefox.

Recursos

O CSS não pode ajudar os usuários a reduzir os dados

Compatibilidade com navegadores

  • x
  • x

Origem

Antes da consulta de mídia prefers-reduced-data, o JavaScript e um servidor podiam mudar o comportamento deles com base na opção de "economia de dados" do navegador ou do sistema operacional de um usuário, mas o CSS não.

Após a consulta de mídia prefers-reduced-data, o CSS pode participar da melhoria da experiência do usuário e salvar dados.

@media (prefers-reduced-data: reduce) {
  picture, video {
    display: none;
  }
}

O CSS anterior é usado neste componente de rolagem de mídia, e a economia pode ser enorme. Dependendo do tamanho da janela de visualização de visitas, maior será a economia de carregamento da página. O salvamento continua à medida que os usuários interagem com os controles de mídia. Todas as imagens têm atributos loading="lazy" e isso, combinado com o CSS que oculta totalmente o elemento, significa que uma solicitação de rede para a imagem nunca é feita.

Captura de tela da interface de carrossel de um programa de TV com muitas miniaturas e títulos.

Para meu teste, em uma janela de visualização de tamanho médio, 40 solicitações e 700 KB de recursos foram carregados inicialmente. À medida que um usuário rola a seleção de mídia, mais solicitações e recursos são carregados. Com o CSS e a consulta de mídia de dados reduzida, 10 solicitações e 172 KB de recursos são carregados. Isso representa meio megabyte de economia e o usuário ainda não rolou nenhuma mídia e, nesse momento, não há outras solicitações feitas.

Captura de tela da interface de carrossel de um programa de TV sem miniaturas e muitos títulos exibidos.

Essa experiência de dados reduzida traz mais vantagens do que apenas a economia de dados. Mais títulos podem ser vistos e não há imagens de capa que chamem a atenção. Muitos usuários navegam no modo de economia de dados porque pagam por megabyte de dados. É muito bom ver o CSS capaz de ajudar aqui.

Recursos

Os recursos de ajuste de rolagem são muito limitados

Antes dessas propostas de ajuste de rolagem, escrever seu próprio JavaScript para gerenciar um carrossel, controle deslizante ou galeria poderia ficar complexo rapidamente, com todos os observadores e gerenciamento de estado. Além disso, se não tomar cuidado, as velocidades de rolagem naturais poderão ser normalizadas pelo script, fazendo com que a interação do usuário pareça um pouco natural e possivelmente desajeitada.

Novas APIs

snapChanging()

Assim que o navegador liberar um filho de ajuste, esse evento será disparado. Isso permite que a interface reflita a falta de um filho de ajuste e o estado de ajuste indeterminado do rolador, já que ele está sendo usado e vai ser direcionado a um novo recurso.

document.querySelector('.snap-carousel').addEventListener('snapchanging', event => {
  console.log('Snap is changing', event.snappedTargetsList);
});
snapChanged()

Assim que o navegador é direcionado a um novo filho e o botão de rolagem é pausado, esse evento é disparado. Isso permite que qualquer interface que dependa do filho selecionado atualize e reflita a conexão.

document.querySelector('.snap-carousel').addEventListener('snapchanged', event => {
  console.log('Snap changed', event.snappedTargetsList);
});
scroll-start

A rolagem nem sempre começa no início. Considere componentes deslizáveis em que o gesto de deslizar para a esquerda ou direita aciona eventos diferentes, ou uma barra de pesquisa que, no carregamento da página, fica oculta até você rolar para a parte de cima. Essa propriedade CSS permite que os desenvolvedores especifiquem que um botão de rolagem precisa começar em um ponto específico.

:root { --nav-height: 100px }

.snap-scroll-y {
  scroll-start-y: var(--nav-height);
}
:snap-target

Esse seletor de CSS fará a correspondência de elementos em um contêiner de ajuste de rolagem que está sendo ajustado pelo navegador.

.card {
  --shadow-distance: 5px;
  box-shadow: 0 var(--shadow-distance) 5px hsl(0 0% 0% / 25%);
  transition: box-shadow 350ms ease;
}

.card:snapped {
  --shadow-distance: 30px;
}

Depois dessas propostas de ajuste de rolagem, criar um controle deslizante, um carrossel ou uma galeria é muito mais fácil, já que o navegador agora oferece conveniências para a tarefa, eliminando observadores e código de orquestração de rolagem em favor do uso de APIs integradas.

Esses recursos de CSS e JS ainda estão em desenvolvimento, mas é importante ficar atento aos polyfills que poderão ajudar na adoção e teste deles em breve.

Recursos

Como alternar entre estados conhecidos

Antes de toggle(), apenas os estados integrados ao navegador já podiam ser usados para estilo e interação. A entrada da caixa de seleção, por exemplo, tem :checked, um estado do navegador gerenciado internamente para a entrada que o CSS pode usar para mudar o elemento visualmente.

Depois de toggle(), os estados personalizados podem ser criados em qualquer elemento para que o CSS mude e use para estilização. Ela permite a alternância em grupos, de bicicleta, em rotas e muito mais.

No exemplo abaixo, o mesmo efeito de um item de lista tachado na conclusão é alcançado, mas sem elementos da caixa de seleção:

<ul class='ingredients'>
   <li>1 banana
   <li>1 cup blueberries
  ...
</ul>

E os estilos CSS toggle() relevantes:

li {
  toggle-root: check self;
}

li:toggle(check) {
  text-decoration: line-through;
}

Se você conhece bem as máquinas de estado, pode notar a quantidade de crossovers com toggle(). Esse recurso permite que os desenvolvedores criem mais do estado em CSS, resultando em maneiras mais claras e semânticas de orquestrar interação e estado.

Recursos

Como personalizar elementos de seleção

Antes de <selectmenu>, o CSS não conseguia personalizar elementos <option> com HTML avançado nem mudar muito a exibição de uma lista de opções. Isso levou os desenvolvedores a carregar bibliotecas externas que recriaram grande parte da funcionalidade de uma <select>, o que acabou sendo muito trabalho.

Depois de <selectmenu>, os desenvolvedores podem fornecer HTML avançado para elementos de opções e estilizá-los o quanto precisarem, além de atender aos requisitos de acessibilidade e fornecer HTML semântico.

No exemplo a seguir, retirado da página de explicação de <selectmenu>, um novo menu de seleção é criado com algumas opções básicas:

<selectmenu>
  <option>Option 1</option>
  <option>Option 2</option>
  <option>Option 3</option>
</selectmenu>

O CSS pode segmentar e estilizar as partes do elemento:

.my-select-menu::part(button) {
  color: white;
  background-color: red;
  padding: 5px;
  border-radius: 5px;
}

.my-select-menu::part(listbox) {
  padding: 10px;
  margin-top: 5px;
  border: 1px solid red;
  border-radius: 5px;
}

Um menu de seleção de visual com cores de destaque vermelhas.

Você pode testar o elemento <selectmenu> no Chromium no Canary com a sinalização de experimentos da Web ativada. Confira os elementos personalizáveis do menu selecionado em 2023 e além.

Recursos

Ancorar um elemento em outro

Antes de anchor(), a posição absoluta e relativa eram estratégias de posição fornecidas aos desenvolvedores para que os elementos filhos se movessem dentro de um elemento pai.

Depois de anchor(), os desenvolvedores podem posicionar elementos em outros elementos, independentemente de serem filhos ou não. Ele também permite que os desenvolvedores especifiquem em qual borda se posicionar e outras comodidades para criar relações de posição entre elementos.

Caso você queira saber mais, há alguns ótimos exemplos e amostras de código na explicação.

Recursos