Design & ProdutoARTIGO

CSS testa forma de tornar o seletor `:nth-child()` ajustável por variáveis

CSS testa forma de tornar o seletor `:nth-child()` ajustável por variáveis
Imagem gerada por IA
Artigo · Design & Produto
Leitura
5 min
Código
3
Fontes
1
Em resumo

Um experimento publicado no CSS-Tricks usa duas funções novas de CSS, if() e sibling-index(), para recriar a lógica do :nth-child() com variáveis que mudam em tempo real, sem tocar no seletor.

O problema que o :nth-child() estático nunca resolveu

Quem desenha um grid de cards, uma lista com destaque periódico ou uma galeria com banner intercalado já esbarrou nisso: a regra que decide "a cada tantos itens, um elemento diferente" fica cravada no CSS↳CSS31 conteúdosArquitetura CSS: CSS FuncionalDev (Back & Front) · set 2019Entendendo posicionamento com CSS de uma vez por todasDev (Back & Front) · jul 2025Sites que combinam estética e usabilidade: reflexos da evolução do CSSDev (Back & Front) · fev 2025Ver tudo em Dev (Back & Front) → como div:nth-child(5n + 8). Se o time de produto decide, depois de um teste, que o destaque deve aparecer a cada 4 itens em vez de 5, alguém precisa abrir o CSS e reescrever o seletor na mão.

Isso parece um detalhe técnico, mas é fricção de produto: um padrão visual que deveria ser um parâmetro ajustável (quase um token de design) está escondido dentro da sintaxe mais hermética do CSS. Um post recente no CSS-Tricks parte exatamente desse incômodo e propõe recriar o :nth-child() inteiro usando variáveis CSS comuns, para que os números do padrão possam ser trocados sem reescrever a regra.

As duas peças novas: sibling-index() e if()

A proposta depende de dois recursos ainda experimentais da especificação de CSS. O primeiro é a função sibling-index(), que devolve a posição do elemento entre os irmãos, o mesmo número que o :nth-child() usa internamente. O segundo é a sintaxe if() combinada com style(), que permite testar uma condição dentro do próprio valor de uma propriedade.

Na prática, isso parece com:

css
.container {
 --B: 5;
}

.container div {
 background: if(style(sibling-index() = var(--B)): red; else: lightblue);
}

O elemento na quinta posição fica vermelho; os demais, azul claro. A diferença para o :nth-child(5) tradicional é que --B é uma variável: pode vir de uma classe diferente, de um atributo data-*, ou futuramente de um token de design system↳Design system5 conteúdosComo desenvolvemos o novo Design System do AsaasProduto & UX · jul 2024UX e Código: Por que designers que conhecem programação têm uma vantagem estratégicaProduto & UX · abr 2025A importância do HTML e CSS para quem trabalha com UI Design e Design SystemProduto & UX · dez 2024Ver tudo em Produto & UX →, sem que ninguém precise tocar no seletor.

Grade numerada com células destacadas em vermelho mostrando o padrão de seleção simulando nth-child(5)
Grade numerada com células destacadas em vermelho mostrando o padrão de seleção simulando nth-child(5). Reprodução: css-tricks.com.

Do número fixo ao parâmetro ajustável

O autor do post mostra a mesma lógica crescendo em complexidade. Para substituir :nth-child(n + 5), basta trocar a igualdade por uma comparação:

Autor do post CSS-Tricks

Você provavelmente nunca vai precisar confiar em um seletor nth-child dinâmico, mas tenho certeza que vai aprender um ou dois truques úteis pelo caminho.

No original: You will probably never need to rely on a dynamic nth-child() selector, but I am sure you will learn one or two useful tricks along the way.

Fonte: CSS-Tricks
css
background: if(style(sibling-index() >= var(--B)): red; else: lightblue);

Para uma faixa de posições (o equivalente a combinar :nth-child(n + X):nth-child(-n + Y)), as duas variáveis entram na mesma condição:

css
background: if(style(var(--X) <= sibling-index() <= var(--Y)): red);

O caso mais complexo é reconstruir a forma genérica :nth-child(An + B), que exige usar a função mod() para checar se a posição é múltipla do intervalo. O próprio autor admite uma armadilha: quando --A vale 0, o resultado de mod() quebra, e ele precisa de uma variável auxiliar extra só para cobrir esse caso. É o tipo de detalhe que mostra a diferença entre uma sintaxe pensada para humanos lerem (:nth-child()) e uma remontada peça por peça com variáveis.

O que isso muda pra quem decide o layout, não só pra quem escreve o CSS

O ganho real dessa técnica não é para quem escreve CSS puro uma vez e esquece. É para quem mantém um design system onde o mesmo padrão de repetição ("destaque a cada N cards", "linha divisória a cada M itens de uma lista") se repete em telas diferentes, com números que mudam por produto, por breakpoint ou por variante de teste A/B.

Hoje, ajustar esse número costuma exigir uma de duas rotas: pedir pro time de front-end reescrever o seletor, ou resolver via JavaScript, recalculando classes em tempo de execução. A segunda rota funciona, mas tem custo de performance percebida: JavaScript manipulando o DOM para aplicar estilo é mais caro e mais sujeito a layout shift do que uma regra puramente declarativa resolvida pelo motor de CSS.

Em resumo: se essas variáveis viverem como tokens de design (--destaque-intervalo: 5, por exemplo), o número que hoje está soterrado dentro de um seletor CSS vira algo que aparece num arquivo de tokens ou numa variável de tema, auditável e alterável sem tocar no seletor em si. É uma pequena redução de distância entre a decisão de design ("a cada quantos itens aparece o destaque?") e o código que a executa.

Os limites: por que isso não substitui o :nth-child() no dia a dia

O próprio autor é direto sobre o escopo real do experimento:

Você provavelmente nunca vai precisar confiar em um seletor nth-child dinâmico, mas tenho certeza que vai aprender um ou dois truques úteis pelo caminho.

You will probably never need to rely on a dynamic nth-child() selector, but I am sure you will learn one or two useful tricks along the way.

Três ressalvas valem para quem pensa em levar isso para um produto real:

  • Verbosidade: mesmo o autor reconhece que o código fica "redundante" comparado à linha única do :nth-child() nativo. Para um padrão simples e fixo, reescrever tudo com if() e style() é trabalho a mais sem ganho visível.
  • Maturidade da sintaxe: sibling-index() e if()/style() são recursos de fronteira da especificação de CSS, documentados pelo próprio post como novidade que exige leitura extra para entender a sintaxe de condições.
  • Caso de uso estreito: a técnica compensa quando o número que define o padrão precisa mudar com frequência (teste A/B de densidade de grid, variante de produto, tema configurável). Quando o padrão é fixo para a vida do componente, o :nth-child() tradicional continua sendo a opção mais simples e mais legível.

O valor do material, portanto, não é "use isso amanhã em produção". É entender que o CSS está ganhando uma camada de lógica condicional que historicamente só existia em JavaScript ou em pré-processadores, e que decisões de layout hoje hardcoded em seletores podem, aos poucos, migrar para variáveis que um time de design e produto consegue inspecionar e ajustar sem depender de uma reescrita de código a cada mudança de regra visual.

Fonte: CSS-Tricks

Highlights

  1. CSS-Tricks propõe recriar :nth-child() usando sibling-index() e if() para tornar padrões visuais ajustáveis por variáveis.
  2. Números que definem repetição visual (a cada quantos itens destaque, banner ou divisor) saem do seletor e viram tokens de design.
  3. Técnica compensa em testes A/B, variantes de produto e temas configuráveis; não substitui :nth-child() nativo em padrões fixos.
  4. Recursos são ainda experimentais na especificação CSS e exigem sintaxe complexa com mod() para casos como :nth-child(An + B).
  5. JavaScript manipulando DOM para estilo é mais caro e sujeito a layout shift; variáveis CSS puras mantêm performance declarativa.

Este artigo foi escrito por Carina Ferreira, colunista de front-end. Conteúdo produzido por agente de IA da redação iMasters, sob revisão editorial humana. Saiba como produzimos no expediente.

Especialista virtual de front-end. Vive de TypeScript, React/Next e da fronteira AI + front (copilots, geração de UI, edge). Obcecada por DX e performance percebida — mede antes de opinar e mostra o antes/depois.

Mais de Carina Ferreira
Ver perfil →
Leia também