12k
All articles

Panda CSS vs StyleX

Compare Panda CSS e StyleX: veja como tokens, prevenção de conflitos de estilos, compilação, temas e valores dinâmicos ajudam a escolher a opção certa.

OpenReplay Team
OpenReplay Team
Panda CSS vs StyleX

Panda CSS e StyleX compilam estilos em CSS atômico estático no momento do build e não enviam nenhum runtime de estilização para o navegador. O que os diferencia é o problema que cada um foi criado para resolver: o Panda impõe um design system, e o StyleX evita que os estilos de um componente colidam com os de outro.

Os dois costumam aparecer na lista de finalistas quando um time quer abandonar o styled-components ou o Emotion sem abrir mão de estilos tipados e colocalizados, e os READMEs de ambos soam quase iguais. Este artigo apresenta a única diferença estrutural entre eles, mostra o mesmo Button escrito em cada um e analisa como essa diferença afeta o fluxo de trabalho, a criação de temas e os valores dinâmicos. Para uma visão mais ampla, veja o estado do CSS-in-JS em 2026.

Principais conclusões

  • Panda CSS e StyleX extraem os estilos em tempo de build para CSS atômico, então nenhum dos dois injeta estilos no navegador durante a renderização.
  • O Panda faz dos design tokens em panda.config.ts a fonte da verdade e gera a partir deles os helpers tipados css(), cva() e styled().
  • No StyleX, cada componente define seus estilos com stylex.create(), e stylex.props() os mescla de forma que o último estilo passado prevalece para uma determinada propriedade.
  • Nenhuma das bibliotecas consegue transformar um valor que só existe em tempo de execução em uma classe atômica. O StyleX encaminha esses valores por meio de variáveis CSS, e a documentação do Panda orienta você a usar recipes, variáveis CSS ou atributos data.
  • O Panda é indicado para um time que está se afastando do seu design system, o StyleX é indicado para uma base de código grande em que o vazamento de estilos é o bug recorrente, e muitos projetos não precisam de nenhum dos dois.

O que Panda CSS e StyleX têm em comum

Panda CSS e StyleX são bibliotecas de CSS-in-JS zero-runtime. Você escreve objetos de estilo em TypeScript, uma etapa de build os extrai e o navegador recebe uma folha de estilos simples composta por classes atômicas de propósito único. Bibliotecas com runtime, como styled-components e Emotion, funcionam de outra forma: elas geram e injetam estilos via JavaScript durante a renderização. Panda e StyleX fazem todo esse trabalho antes de o código ir para produção. Se quiser conhecer a versão mais antiga dessa mesma divisão, Linaria vs styled-components aborda o tema.

Como a saída é CSS estático, nenhuma das bibliotecas precisa de um context provider nem de um injetor de estilos em tempo de renderização. É por isso que ambas funcionam com React Server Components: nenhum código de estilização é executado durante a renderização no servidor ou no cliente. Na saída atômica, cada classe define uma única propriedade, então o tamanho da folha de estilos cresce de acordo com o número de declarações únicas, e não com o número de componentes.

Panda CSS: design system em primeiro lugar

O Panda CSS trata o design system como a fonte da verdade. Os tokens definidos em panda.config.ts alimentam uma etapa de geração de código, que produz os helpers tipados css(), cva() e styled() para o restante da base de código. O Panda vem do time por trás do Chakra UI, e essa origem em bibliotecas de componentes fica evidente.

Executar o comando panda codegen cria um diretório styled-system/ no seu projeto. Os componentes importam seus helpers desse diretório, e os tipos contidos nele são gerados a partir dos seus tokens. Se brand for um token de cor, bg: 'brand' aparece no autocomplete. Com a opção de configuração strictTokens, um valor hexadecimal bruto passa a gerar um erro de tipo.

Os recipes transformam isso em APIs de componentes. O cva() recebe um estilo base, variants nomeadas e defaultVariants, e retorna uma função que mapeia props de variante para nomes de classe. O design system decide quais opções existem, e os componentes escolhem a partir dessa lista.

StyleX: colisões em primeiro lugar

O StyleX trata as colisões de estilo como o problema central. Cada componente define seus próprios objetos de estilo com stylex.create(), e stylex.props() os mescla de forma determinística, de modo que, quando dois estilos definem a mesma propriedade, o último passado prevalece. A ordem da folha de estilos e a especificidade dos seletores não interferem. O StyleX é um projeto open source da Meta e é a camada de estilização por trás de design systems como o Astryx.

const styles = stylex.create({
  a: { color: 'red' },
  b: { color: 'blue' },
})
stylex.props(styles.a, styles.b) // blue
stylex.props(styles.b, styles.a) // red

As regras de mesclagem do StyleX também cobrem propriedades shorthand. O guia Thinking in StyleX explica que um conflito entre uma propriedade shorthand e uma longhand é sempre resolvido da mesma maneira: por padrão, marginTop sobrescreve margin, independentemente de qual delas você passe primeiro. A compilação acontece no plugin Babel do StyleX, e as integrações oficiais com bundlers e com o PostCSS são construídas sobre ele.

O mesmo Button estilizado das duas formas

Os Buttons em Panda CSS e em StyleX abaixo expõem a mesma prop intent. A diferença está em onde ficam as decisões de estilização.

// Panda: panda.config.ts defines theme.extend.tokens.colors.brand = { value: '#2563eb' }
import { cva } from '../styled-system/css'

const button = cva({
  base: { px: '4', py: '2', borderRadius: 'md', fontWeight: 'semibold' },
  variants: {
    intent: {
      primary: { bg: 'brand', color: 'white' },
      ghost: { bg: 'transparent', color: 'brand' },
    },
  },
  defaultVariants: { intent: 'primary' },
})

export function Button({ intent, ...props }) {
  return <button className={button({ intent })} {...props} />
}
// StyleX
import * as stylex from '@stylexjs/stylex'

const styles = stylex.create({
  base: { paddingInline: 16, paddingBlock: 8, borderRadius: 6, fontWeight: 600 },
  primary: { backgroundColor: '#2563eb', color: 'white' },
  ghost: { backgroundColor: 'transparent', color: '#2563eb' },
})

export function Button({ intent = 'primary', style, ...props }) {
  return <button {...props} {...stylex.props(styles.base, styles[intent], style)} />
}

Na versão em Panda, bg: 'brand' só passa na checagem de tipos porque brand existe na configuração e o codegen gerou um tipo correspondente. Na versão em StyleX, cada variante é um objeto próprio, e o style do consumidor é passado por último. Sempre que ele define a mesma propriedade que a base ou a variante, o valor do consumidor prevalece, e não há especificidade a ser combatida. Os helpers do Panda limitam quais valores um desenvolvedor pode usar. A regra de mesclagem do StyleX limita como os estilos de um componente podem sobrescrever os de outro.

Consequências práticas de escolher Panda CSS ou StyleX

A diferença de origem se manifesta em três áreas do dia a dia: como o build funciona, como a criação de temas funciona e o que acontece com valores que só existem em tempo de execução.

CritérioPanda CSSStyleX
Etapa de buildO codegen gera styled-system/; o plugin PostCSS ou a CLI extrai o CSSO plugin Babel compila as chamadas a stylex.create
TemasTokens na configuraçãodefineVars mais createTheme
Valores em tempo de execuçãoNão extraíveis; use recipes, variáveis CSS, atributos dataEncaminhados por meio de variáveis CSS

Fluxo de trabalho: codegen vs plugin de compilador

No Panda, um artefato gerado fica entre a sua configuração e os seus componentes, então alterar um token exige gerar novamente o styled-system/. O StyleX não tem diretório gerado. O plugin Babel transforma cada módulo no próprio local em que foi escrito, e a configuração do plugin controla como imports e variáveis são resolvidos.

Temas: tokens vs variáveis

No Panda, o tema é o conjunto de tokens: altere brand na configuração e todos os usos mudam no próximo build. No StyleX, a criação de temas é um mecanismo de sobrescrita adicionado por cima dos estilos de cada componente. stylex.defineVars declara variáveis em um arquivo .stylex.ts, e stylex.createTheme produz sobrescritas que você aplica a um elemento ancestral:

// tokens.stylex.ts
import * as stylex from '@stylexjs/stylex'
export const colors = stylex.defineVars({ brand: '#2563eb' })

// app.tsx
import * as stylex from '@stylexjs/stylex'
import { colors } from './tokens.stylex'

const dark = stylex.createTheme(colors, { brand: '#60a5fa' })
<div {...stylex.props(dark)}>{children}</div>

As APIs de temas do StyleX só funcionam depois que a opção unstable_moduleResolution do plugin Babel é configurada.

Valores dinâmicos: onde o zero-runtime fica complicado

Um extrator em tempo de build só enxerga os valores escritos no código-fonte. Um valor que só é conhecido em tempo de execução, como uma cor escolhida pelo usuário, não pode virar uma classe atômica em nenhuma das bibliotecas. O guia de estilização dinâmica do Panda explica que o extrator ignora tudo o que não consegue ler do código-fonte e orienta o uso de recipes, variáveis CSS ou atributos data-*. O StyleX lida com estilos dinâmicos de outra forma: o compilador gera uma classe fixa que aponta para uma variável CSS, e o valor em tempo de execução é atribuído a essa variável no elemento.

Panda CSS vs StyleX: qual é o seu problema?

Escolha com base no problema que você tem, e não na lista de funcionalidades. Um time pequeno cuja UI vive se desviando do design system tem exatamente o problema para o qual o Panda foi criado: os tokens viram tipos, e valores fora do sistema deixam de compilar. Uma base de código grande em que os estilos de um componente vivem vazando para outro tem exatamente o problema para o qual o StyleX foi criado: cada componente é dono dos seus estilos, e a ordem de mesclagem no ponto de chamada determina o resultado.

Muitos projetos não têm nenhum dos dois problemas. Para eles, CSS Modules ou um framework utilitário resolvem a questão com menos ferramental de build do que qualquer uma das bibliotecas exige. Para uma comparação entre outras duas abordagens de estilização, veja Tailwind vs Sass.

Antes de se comprometer com qualquer uma das bibliotecas, identifique o bug de estilização que o seu time vive corrigindo. Se for desvio do design, faça o protótipo de um recipe no Panda. Se forem conflitos de sobrescrita, migre um componente compartilhado para o StyleX e observe como os consumidores dele se comportam.

Perguntas frequentes

Como os estados de hover e as media queries diferem entre Panda CSS e StyleX?

No StyleX, pseudoclasses e media queries ficam dentro do valor de uma propriedade, como um objeto de condições, e esse objeto precisa de uma entrada default, que pode ser definida como null. Os pseudoelementos, como ::placeholder, são a exceção: eles são escritos como uma chave própria no nível superior do namespace. O Panda aceita condições dentro de uma propriedade, como em bg: { base: 'red.500', _hover: 'red.700' }, ou como objetos de condição, usando nomes nativos como _hover e chaves de breakpoint mobile-first como md e lg.

O StyleX consegue estilizar elementos filhos da mesma forma que os seletores arbitrários do Panda?

Não diretamente. O StyleX não permite seletores arbitrários nem estilização à distância, enquanto o css() do Panda aceita seletores arbitrários como '& > *'. O StyleX 0.16.0 adicionou as APIs stylex.when (ancestor, descendant, anySibling, siblingBefore e siblingAfter). Você marca um elemento com stylex.defaultMarker(), e outro elemento altera seus estilos quando o elemento marcado recebe hover, foco ou corresponde a um atributo. As variantes descendant, anySibling e siblingAfter dependem do seletor CSS :has(). Definir uma variável de defineVars em um elemento pai é outro caminho documentado.

O stylex.props() é executado no navegador?

Às vezes, e apenas como uma pequena etapa de mesclagem. O compilador do StyleX transforma as chamadas a stylex.create() em CSS atômico estático no momento do build e, quando os estilos são criados e usados no mesmo arquivo, pode remover completamente a chamada a stylex.props(). Quando os estilos atravessam os limites entre arquivos, o stylex.props() é executado como uma função que mescla os objetos de estilo compilados da esquerda para a direita e retorna as props className e style para o React. Ele nunca gera nem injeta CSS no navegador. Para frameworks que não são React, como Solid, Svelte, Qwik e Vue, o StyleX também oferece o stylex.attrs().

Qual é a diferença entre strictTokens e strictPropertyValues no Panda CSS?

O strictTokens se aplica a propriedades baseadas em tokens, como color, bg e borderColor: com ele ativado, apenas valores de token são aceitos nelas. O strictPropertyValues se aplica a uma lista fixa de propriedades com valores de palavra-chave conhecidos, como display, position e overflow: com ele ativado, o Panda lança um erro quando um valor não é uma dessas palavras-chave. Ambos são ativados no panda.config.ts. Em qualquer um dos casos, envolver um valor bruto em colchetes, como em [123px], faz com que ele seja aceito sem erro de TypeScript.

DevTools for the frontend

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.