NUCBA
27 de enero de 2026
producto

Implementá un sistema de espaciado consistente con CSS variables

Tutorial paso a paso: extraé valores de Figma, definilos en variables CSS, conectalos a componentes React, y sincronizá con el equipo.

Equipo NUCBA

Equipo NUCBA

7 min de lectura

Implementá un sistema de espaciado consistente con CSS variables

Tu equipo usa 14 valores de padding diferentes. Tres espaciados que "se ven igual" pero están definidos con 16px, 1rem y 18px. Un desarrollador pregunta en Slack: "¿cuánto espacio va entre el título y el botón?" y nadie responde con certeza. Este caos tiene solución: un sistema de espaciado basado en CSS variables que se sincroniza entre diseño y código.

La consistencia visual no sale de "tener buen ojo". Sale de un sistema que elimina las decisiones arbitrarias y obliga a usar valores predefinidos. Este tutorial te muestra cómo extraer los valores desde Figma, definirlos como variables CSS, conectarlos a tus componentes React, y mantener todo sincronizado con el equipo.

Extraé y documentá los valores desde Figma

Antes de escribir una línea de CSS, necesitás saber qué valores existen realmente en tu diseño. Abrí Figma y seleccioná todos los frames principales de tu producto. Usá el plugin "Design Lint" o revisá manualmente las propiedades de espaciado (padding, gap, margins) de cada componente.

Lo que vas a encontrar probablemente te sorprenda: valores inconsistentes que surgieron de decisiones aisladas. Documentalos todos en una hoja de cálculo con tres columnas: valor actual, frecuencia de uso, y contexto (botones, cards, layout principal).

Una vez que tenés el inventario completo, definí tu escala. La más común es la escala de 8 puntos (4, 8, 12, 16, 24, 32, 48, 64, 96, 128), pero podés usar la que mejor se ajuste a tu producto. Lo importante es que sea predecible y cubra el 95% de los casos de uso.

Valores sugeridos para empezar:

/* Escala básica de espaciado */
--space-xs: 4px;    /* Espacios internos pequeños */
--space-sm: 8px;    /* Padding de inputs, badges */
--space-md: 16px;   /* Padding de botones, cards */
--space-lg: 24px;   /* Espaciado entre secciones */
--space-xl: 32px;   /* Separación de bloques */
--space-2xl: 48px;  /* Márgenes grandes */
--space-3xl: 64px;  /* Espaciado de hero sections */

Ahora unificá los valores en Figma. Creá variables locales con estos nombres exactos. Reemplazá cada instancia de espaciado manual por una referencia a la variable correspondiente. Este proceso puede tomar horas, pero es el trabajo que hace que todo lo demás funcione.

Definí las variables CSS en tu proyecto

Creá un archivo tokens.css en la raíz de tu carpeta de estilos. Este archivo va a ser la única fuente de verdad para todos los valores de espaciado de tu producto.

/* tokens.css */
:root {
  /* Espaciado base */
  --space-xs: 0.25rem;   /* 4px */
  --space-sm: 0.5rem;    /* 8px */
  --space-md: 1rem;      /* 16px */
  --space-lg: 1.5rem;    /* 24px */
  --space-xl: 2rem;      /* 32px */
  --space-2xl: 3rem;     /* 48px */
  --space-3xl: 4rem;     /* 64px */
  
  /* Espaciado semántico (opcional pero útil) */
  --space-input-padding: var(--space-sm);
  --space-button-padding: var(--space-md);
  --space-card-padding: var(--space-lg);
  --space-section-gap: var(--space-2xl);
}

Usamos rem en lugar de px porque respeta las preferencias de accesibilidad del usuario (tamaño de fuente del navegador). Si un usuario tiene configurado el navegador a 20px base en lugar de 16px, todos los espacios escalarán proporcionalmente.

Importá este archivo antes que cualquier otro CSS:

// main.jsx o App.jsx
import './styles/tokens.css';
import './styles/global.css';

Las variables CSS tienen una ventaja crucial sobre SASS o variables JavaScript: se actualizan en tiempo real. Si cambiás el valor de --space-md, todos los componentes que lo usan se actualizan inmediatamente, sin recompilar.

Conectá las variables a tus componentes React

Ahora viene la parte donde el sistema toma vida. En lugar de escribir valores arbitrarios en cada componente, vas a referenciar las variables CSS.

Enfoque 1: CSS directo

/* Button.module.css */
.button {
  padding: var(--space-sm) var(--space-md);
  gap: var(--space-xs);
}

.card {
  padding: var(--space-lg);
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

Enfoque 2: Utility classes

Si usás Tailwind, podés extender el config para usar tus variables:

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      spacing: {
        'xs': 'var(--space-xs)',
        'sm': 'var(--space-sm)',
        'md': 'var(--space-md)',
        'lg': 'var(--space-lg)',
        'xl': 'var(--space-xl)',
        '2xl': 'var(--space-2xl)',
        '3xl': 'var(--space-3xl)',
      }
    }
  }
}

Ahora podés usar p-md, gap-lg, mt-xl y todos respetan tu sistema.

Enfoque 3: Props tipadas en componentes

// Spacer.tsx
type SpaceSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl';

interface SpacerProps {
  size: SpaceSize;
  direction?: 'horizontal' | 'vertical';
}

export const Spacer = ({ size, direction = 'vertical' }: SpacerProps) => {
  const style = {
    [direction === 'vertical' ? 'height' : 'width']: `var(--space-${size})`
  };
  
  return <div style={style} />;
};

Uso:

<h2>Título de sección</h2>
<Spacer size="lg" />
<p>Contenido del párrafo...</p>

Este componente obliga a usar valores del sistema. No hay forma de poner un espaciado arbitrario sin que TypeScript te frene.

Sincronizá el sistema con el equipo

Un sistema de espaciado solo funciona si todo el equipo lo usa. Acá es donde la mayoría de los proyectos fallan: crean el sistema pero no lo hacen obligatorio ni visible.

Documentación viva

Creá una página interna (puede ser un componente de Storybook o una ruta en tu app de desarrollo) que muestre todos los valores de espaciado en contexto real:

// SpacingDocs.tsx
const sizes = ['xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl'];

export const SpacingDocs = () => (
  <div>
    <h1>Sistema de espaciado</h1>
    {sizes.map(size => (
      <div key={size} style={{ marginBottom: 'var(--space-lg)' }}>
        <code>--space-{size}</code>
        <div 
          style={{ 
            height: `var(--space-${size})`,
            width: '100%',
            backgroundColor: '#3b82f6',
            marginTop: 'var(--space-xs)'
          }} 
        />
      </div>
    ))}
  </div>
);

Reglas de linting

Si usás Stylelint, podés prohibir valores numéricos directos en propiedades de espaciado:

// .stylelintrc.json
{
  "rules": {
    "declaration-property-value-disallowed-list": {
      "/^(padding|margin|gap)/": ["/^\\d+/"]
    }
  }
}

Esto hace que el editor muestre un error si alguien escribe padding: 16px en lugar de padding: var(--space-md).

Tokens como fuente de verdad compartida

Usá Style Dictionary para transformar un archivo JSON en variables CSS, tokens de Figma, y valores iOS/Android:

// tokens.json
{
  "spacing": {
    "xs": { "value": "4" },
    "sm": { "value": "8" },
    "md": { "value": "16" },
    "lg": { "value": "24" },
    "xl": { "value": "32" }
  }
}

Style Dictionary genera automáticamente:

  • Variables CSS para web
  • Tokens JSON para Figma (importables con plugins)
  • Constantes Swift para iOS
  • Resources XML para Android

Cada vez que actualizás tokens.json y ejecutás el script de build, todos los formatos se regeneran. El diseño y el código están sincronizados desde la fuente.

Checklist para implementar el sistema

Antes de considerar que tu sistema de espaciado está listo, verificá estos puntos:

  • Todos los valores de espaciado de Figma están mapeados a variables
  • El archivo tokens.css es importado antes que cualquier otro estilo
  • Existe documentación visual de cada valor de espaciado en contexto
  • Los componentes principales usan variables en lugar de valores literales
  • El linter bloquea la creación de nuevos valores arbitrarios
  • Todo el equipo sabe dónde consultar los valores disponibles
  • Hay un proceso definido para proponer nuevos valores (spoiler: debe ser excepcional)

Preguntas frecuentes

¿Qué hago con los valores de espaciado que no encajan en la escala?

Primero, preguntate si realmente no encaja o si estás inventando un caso especial. El 90% de las veces, uno de los valores existentes funciona. Si después de probar no hay forma de que funcione, usá un valor intermedio como calc(var(--space-md) + var(--space-xs)). Si este patrón se repite más de 3 veces en el producto, considerá agregarlo como valor oficial.

¿Es mejor usar rem, px, o valores relativos como em?

rem para espaciado estructural (layouts, componentes). em para espaciado que debe escalar con el tamaño de fuente del elemento (ej: padding interno de un botón con texto grande). px solo si estás haciendo algo que requiere precisión de píxel (ej: bordes de 1px, alineación con grillas de diseño gráfico). En la mayoría de los casos, rem es la respuesta correcta.

¿Cómo convenzo al equipo de que use el sistema en lugar de valores manuales?

No los convenzas. Hacé que sea más fácil usar el sistema que no usarlo. Autocomplete en el IDE, componentes con props tipadas que solo aceptan valores del sistema, linter que bloquea valores arbitrarios. Si alguien puede escribir padding: 13px sin fricción, lo va a hacer. Si el editor le sugiere padding: var(--space-md) apenas escribe "pad", lo va a usar.

¿Te gustó este artículo?

Descubre nuestros cursos y carreras para llevar tus habilidades al siguiente nivel.