12k
All articles

Panda CSS vs StyleX

Compara Panda CSS y StyleX: descubre cómo los tokens, la prevención de conflictos de estilos, el proceso de compilación, los temas y los valores dinámicos orientan tu elección.

OpenReplay Team
OpenReplay Team
Panda CSS vs StyleX

Panda CSS y StyleX compilan los estilos a CSS atómico estático en tiempo de compilación y no envían ningún runtime de estilos al navegador. Lo que los distingue es el problema que cada uno se diseñó para resolver: Panda impone un sistema de diseño, y StyleX evita que los estilos de un componente colisionen con los de otro.

Ambos aparecen en la lista de candidatos cuando un equipo quiere abandonar styled-components o Emotion sin renunciar a estilos tipados y colocalizados, y los README de los dos suenan casi idénticos. Este artículo expone la única diferencia estructural entre ellos, muestra el mismo Button escrito con cada uno y analiza cómo esa diferencia afecta al flujo de trabajo, a la tematización y a los valores dinámicos. Para una visión más amplia, consulta el estado de CSS-in-JS en 2026.

Puntos clave

  • Tanto Panda CSS como StyleX extraen los estilos en tiempo de compilación a CSS atómico, por lo que ninguno de los dos inyecta estilos en el navegador durante el renderizado.
  • Panda convierte los design tokens de panda.config.ts en la fuente de verdad y genera a partir de ellos los helpers tipados css(), cva() y styled().
  • StyleX hace que cada componente defina sus estilos con stylex.create(), y stylex.props() los fusiona de modo que, para una propiedad determinada, prevalece el último estilo pasado.
  • Ninguna de las dos librerías puede convertir en una clase atómica un valor que solo existe en tiempo de ejecución. StyleX canaliza esos valores a través de variables CSS, y la documentación de Panda recomienda usar recipes, variables CSS o atributos data.
  • Panda encaja con un equipo que se está alejando de su sistema de diseño, StyleX encaja con una base de código grande en la que la fuga de estilos es el bug recurrente, y muchos proyectos no necesitan ninguno de los dos.

Lo que tienen en común Panda CSS y StyleX

Panda CSS y StyleX son librerías CSS-in-JS de runtime cero. Escribes objetos de estilo en TypeScript, un paso de compilación los extrae y el navegador recibe una hoja de estilos simple compuesta por clases atómicas de propósito único. Las librerías con runtime, como styled-components y Emotion, funcionan de otra manera: generan e inyectan los estilos mediante JavaScript durante el renderizado. Panda y StyleX hacen todo ese trabajo antes de que el código se despliegue. Si quieres ver la versión anterior de esta misma división, Linaria vs styled-components la aborda.

Como el resultado es CSS estático, ninguna de las dos librerías necesita un context provider ni un inyector de estilos en tiempo de renderizado. Por eso ambas funcionan con React Server Components: no se ejecuta código de estilos durante el renderizado en el servidor ni en el cliente. En una salida atómica, cada clase define una sola propiedad, de modo que el tamaño de la hoja de estilos crece con el número de declaraciones únicas y no con el número de componentes.

Panda CSS: el sistema de diseño primero

Panda CSS trata el sistema de diseño como la fuente de verdad. Los tokens definidos en panda.config.ts alimentan un paso de generación de código que produce los helpers tipados css(), cva() y styled() para el resto de la base de código. Panda proviene del equipo que creó Chakra UI, y su origen en las librerías de componentes se nota.

Al ejecutar el comando panda codegen se escribe un directorio styled-system/ en tu proyecto. Los componentes importan sus helpers desde ese directorio, y los tipos que contiene se generan a partir de tus tokens. Si brand es un token de color, bg: 'brand' se autocompleta. Con la opción de configuración strictTokens, un valor hexadecimal literal se convierte en un error de tipos.

Las recipes convierten esto en APIs de componentes. cva() recibe un estilo base, variants con nombre y defaultVariants, y devuelve una función que asigna las props de variante a nombres de clase. El sistema de diseño decide qué opciones existen, y los componentes eligen de esa lista.

StyleX: las colisiones primero

StyleX trata las colisiones de estilos como el problema central. Cada componente define sus propios objetos de estilo con stylex.create(), y stylex.props() los fusiona de forma determinista, de modo que, cuando dos estilos definen la misma propiedad, prevalece el último que se pasa. El orden de la hoja de estilos y la especificidad de los selectores no intervienen. StyleX es un proyecto open source de Meta y es la capa de estilos sobre la que se construyen sistemas de diseño como 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

Las reglas de fusión de StyleX también cubren las propiedades abreviadas (shorthands). Thinking in StyleX explica que un conflicto entre una propiedad abreviada y una propiedad desglosada (longhand) siempre se resuelve de la misma manera: por defecto, marginTop sobrescribe a margin independientemente de cuál pases primero. La compilación se realiza en el plugin de Babel de StyleX, y las integraciones oficiales con bundlers y PostCSS se construyen sobre él.

El mismo Button estilizado de ambas formas

Los Button de Panda CSS y StyleX que aparecen a continuación exponen la misma prop intent. La diferencia está en dónde residen las decisiones de estilo.

// 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)} />
}

En la versión de Panda, bg: 'brand' solo supera la comprobación de tipos porque brand existe en la configuración y el codegen ha emitido un tipo correspondiente. En la versión de StyleX, cada variante es su propio objeto y el style del consumidor se pasa en último lugar. Siempre que defina la misma propiedad que la base o la variante, prevalece el valor del consumidor, y no hay especificidad contra la que luchar. Los helpers de Panda limitan qué valores puede usar un desarrollador. La regla de fusión de StyleX limita cómo los estilos de un componente pueden sobrescribir los de otro.

Consecuencias prácticas de elegir Panda CSS o StyleX

La diferencia de origen se manifiesta en tres áreas del día a día: cómo funciona la compilación, cómo funciona la tematización y qué ocurre con los valores que solo existen en tiempo de ejecución.

CriterioPanda CSSStyleX
Paso de compilaciónEl codegen escribe styled-system/; el plugin de PostCSS o la CLI extraen el CSSEl plugin de Babel compila las llamadas a stylex.create
TematizaciónTokens en la configuracióndefineVars más createTheme
Valores en tiempo de ejecuciónNo extraíbles; usa recipes, variables CSS o atributos dataCanalizados a través de variables CSS

Flujo de trabajo: codegen vs plugin del compilador

En Panda, entre tu configuración y tus componentes hay un artefacto generado, por lo que cambiar un token implica regenerar styled-system/. StyleX no tiene ningún directorio generado. El plugin de Babel transforma cada módulo allí donde está escrito, y la configuración del plugin controla cómo se resuelven los imports y las variables.

Tematización: tokens vs variables

En Panda, el tema es el conjunto de tokens: cambia brand en la configuración y todos sus usos cambiarán en la siguiente compilación. En StyleX, la tematización es un mecanismo de sobrescritura que se añade encima de los estilos de cada componente. stylex.defineVars declara variables en un archivo .stylex.ts, y stylex.createTheme genera sobrescrituras que se aplican a un elemento ancestro:

// 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>

Las APIs de tematización de StyleX solo funcionan una vez configurada la opción unstable_moduleResolution del plugin de Babel.

Valores dinámicos: donde el runtime cero se complica

Un extractor que actúa en tiempo de compilación solo ve los valores escritos en el código fuente. Un valor que solo se conoce en tiempo de ejecución, como un color elegido por el usuario, no puede convertirse en una clase atómica en ninguna de las dos librerías. La guía de estilos dinámicos de Panda explica que su extractor omite todo lo que no puede leer del código fuente y te orienta hacia las recipes, las variables CSS o los atributos data-*. StyleX gestiona los estilos dinámicos de otra forma: el compilador emite una clase fija que apunta a una variable CSS, y el valor en tiempo de ejecución se escribe en esa variable sobre el elemento.

Panda CSS vs StyleX: ¿qué problema tienes?

Elige en función del problema que tienes, no de la lista de funcionalidades. Un equipo pequeño cuya interfaz se aleja constantemente de su sistema de diseño tiene el problema para el que se creó Panda: los tokens se convierten en tipos y los valores ajenos al sistema dejan de compilar. Una base de código grande en la que los estilos de un componente se filtran continuamente a otro tiene el problema para el que se creó StyleX: cada componente es dueño de sus estilos, y el orden de fusión en el punto de llamada determina el resultado.

Muchos proyectos no tienen ninguno de los dos problemas. Para ellos, CSS Modules o un framework de utilidades cumplen su función con menos herramientas de compilación de las que necesita cualquiera de estas librerías. Para comparar otros dos enfoques de estilos, consulta Tailwind vs Sass.

Antes de comprometerte con cualquiera de las dos librerías, identifica el bug de estilos que tu equipo corrige una y otra vez. Si se trata de desviaciones del diseño, crea un prototipo de una recipe en Panda. Si se trata de conflictos de sobrescritura, migra un componente compartido a StyleX y observa cómo se comportan sus consumidores.

Preguntas frecuentes

¿En qué se diferencian los estados hover y las media queries entre Panda CSS y StyleX?

En StyleX, las pseudoclases y las media queries se escriben dentro del valor de una propiedad como un objeto de condiciones, y ese objeto necesita una entrada default, que puedes establecer en null. Los pseudoelementos como ::placeholder son la excepción: se escriben como su propia clave en el nivel superior del namespace. Panda acepta condiciones dentro de una propiedad, como en bg: { base: 'red.500', _hover: 'red.700' }, o como objetos de condición, usando nombres integrados como _hover y claves de breakpoints mobile-first como md y lg.

¿Puede StyleX aplicar estilos a elementos hijos como lo hacen los selectores arbitrarios de Panda?

No directamente. StyleX no permite selectores arbitrarios ni aplicar estilos a distancia, mientras que css() de Panda acepta selectores arbitrarios como '& > *'. StyleX 0.16.0 añadió las APIs stylex.when (ancestor, descendant, anySibling, siblingBefore y siblingAfter). Marcas un elemento con stylex.defaultMarker(), y otro elemento cambia sus estilos cuando el elemento marcado recibe hover, recibe el foco o coincide con un atributo. Las variantes descendant, anySibling y siblingAfter dependen del selector CSS :has(). Definir una variable de defineVars en un elemento padre es otra vía documentada.

¿Se ejecuta stylex.props() en el navegador?

A veces, y solo como un pequeño paso de fusión. El compilador de StyleX convierte las llamadas a stylex.create() en CSS atómico estático en tiempo de compilación y, cuando los estilos se crean y se usan en el mismo archivo, puede eliminar por completo la llamada a stylex.props(). Cuando los estilos cruzan los límites de un archivo, stylex.props() se ejecuta como una función que fusiona de izquierda a derecha los objetos de estilo compilados y devuelve las props className y style para React. Nunca genera ni inyecta CSS en el navegador. Para frameworks distintos de React, como Solid, Svelte, Qwik y Vue, StyleX también ofrece stylex.attrs().

¿Cuál es la diferencia entre strictTokens y strictPropertyValues en Panda CSS?

strictTokens afecta a las propiedades respaldadas por tokens, como color, bg y borderColor: si está activada, solo se aceptan valores de tokens en ellas. strictPropertyValues afecta a una lista fija de propiedades con valores de palabra clave conocidos, como display, position y overflow: si está activada, Panda lanza un error cuando un valor no es una de esas palabras clave. Ambas se activan en panda.config.ts. En cualquier caso, envolver un valor literal entre corchetes, como en [123px], permite que pase sin error 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.