FNSP Web Page

CSS moderno: a cor calculada, o :is() e o aninhamento

Há uma linha no CSS deste site que resume o que mudou no CSS da última década:

--cor-tag: oklch(0.45 0.13 var(--tom-tag, 144));

Uma propriedade personalizada a servir de argumento a uma função de cor. Não é um valor com nome — é uma entrada num cálculo que o browser faz.

1. O que aquela linha resolve

Cada etiqueta do blogue guarda um número na base de dados: onde cai no círculo cromático, de 0 a 359. Mais nada. A luminosidade (0.45) e o croma (0.13) estão fixos no CSS, iguais para todas.

A consequência é a parte boa: quem cria uma etiqueta escolhe o tom, e não tem como escolher mal. O contraste está garantido para qualquer um dos 360 valores, porque os dois números que o determinam não estão à escolha de ninguém. E o 144 dentro do var() é o valor de recurso — o verde da casa, para quando o tom não está definido.

Isto só funciona em oklch. Em HSL, a mesma luminosidade dá cores com claridade percebida muito diferente conforme o tom — um amarelo a 50% salta, um azul a 50% afunda. No oklch a luminosidade é perceptual, e 0.45 pesa o mesmo em todo o círculo. É o que torna a garantia possível, e é a razão de ser do espaço de cor, não um detalhe de sintaxe.

E o que fica dito por omissão: não há JavaScript nenhum nisto. A cor é calculada onde devia ser, que é no CSS.

2. :is() e :where(), e a única diferença que importa

/* Em vez de tres seletores repetidos */
:is(h1, h2, h3) > code { font-size: 0.9em; }

Encurtam listas, o que é cómodo. O que interessa é a diferença entre os dois: o :is() assume a especificidade mais alta dos seus argumentos; o :where() tem especificidade zero, sempre.

Daí a regra prática: :where() para estilos de base, que se querem fáceis de sobrepor; :is() quando se quer mesmo ganhar. Escrever :is() onde se queria :where() produz aquela folha que obriga a um !important três meses depois.

3. Aninhamento, agora nativo

.cartao {
  border: 1px solid var(--border);

  &:hover { background: var(--accent); }

  h3 { font-weight: 600; }
}

Deixou de ser preciso um pré-processador para isto. Com o aviso que o Sass já devia ter ensinado: o aninhamento é a nova especificidade. Três níveis produzem um seletor que ninguém sobrepõe sem brigar, e a profundidade esconde-o — na folha parecem três linhas arrumadas.

Dois níveis, e o & para estados. Daí para baixo, uma classe nova sai mais barato.

4. Container queries: a pergunta certa

Uma media query pergunta pelo tamanho da janela. Quase sempre, o que o componente precisa de saber é o seu próprio tamanho — e as duas coisas só coincidem enquanto ele ocupar a largura toda.

.lista { container-type: inline-size; }

@container (min-width: 24rem) {
  .cartao { display: grid; grid-template-columns: auto 1fr; }
}

Este site ainda não as usa, e há um sítio onde dariam jeito imediato: os cartões do «Continuar a ler», que aparecem numa coluna em ecrã pequeno e em duas no resto. Hoje a decisão está escrita em função da janela; o cartão é que sabe se tem 300 ou 600 píxeis.

A diferença de fundo é que um componente passa a poder ser colocado em qualquer sítio e adaptar-se — em vez de trazer consigo um conjunto de suposições sobre onde é que vai aparecer.

5. Duas de uma linha cada

  • color-mix() — misturar duas cores no CSS, sem gerar variantes à mão: color-mix(in oklab, var(--cor) 20%, transparent) é um fundo esbatido da mesma cor, sem uma variável nova.

  • :has() — o seletor que faltava, e que já teve artigo próprio: permite estilizar um elemento pelo que ele contém.

O resumo

O que estas peças têm em comum não é serem novas — é tirarem lógica ao JavaScript. Uma propriedade personalizada dentro de uma função de cor transforma um número guardado na base numa cor com contraste garantido, sem uma linha de código a correr no browser. É aí que o CSS moderno paga, e não nas chaves que poupa.

Comentários

Ainda ninguém comentou este artigo.

Voltar ao blog

Gostávamos de saber quantas pessoas visitam o site, com o Google Analytics. Sem a sua autorização não corre nada. Política de Privacidade.