Módulo 4: Scales Color And Contrast

La escala de espaciado

Descripción

Toda pantalla es, en el fondo, cosas separadas por huecos: el espacio entre el precio y el botón, el relleno dentro de la tarjeta, el margen entre dos productos del catálogo. Esos huecos son la mitad invisible del diseño —cuando están bien, nadie los nota; cuando están mal, todo "se siente desordenado" aunque nadie sepa decir por qué—. La pregunta de esta lección es de dónde salen esos huecos. La respuesta de un sistema es una escala de espaciado: una sola base pequeña (4px) de la que se derivan todos los espacios como múltiplos, de modo que ningún padding ni gap ni margen sea un número inventado. Vas a construir space(step) sobre esa base, ver la serie completa (space-1 a space-12), y entender por qué esa regularidad es lo que hace que una UI se sienta ordenada.

Conexión con el módulo. Esta es la primera de las dos escalas de tamaño del módulo (la otra, la tipográfica, es la lección 3). Es el valor detrás de las utilidades de espacio que usaste en el módulo 3 sin cuestionar: p-4 daba 1rem, gap-2 daba 0.5rem —esos valores salían de esta escala—. Aquí los construyes de raíz. En el módulo 3 consumiste la escala; ahora la fabricas. Y es la base del proyecto (lección 8), donde la escala de espaciado de Mercado es una de las tres que definirás.

Una analogía: los tallajes de ropa, aplicados al espacio

Una marca de ropa no corta cada prenda a una medida arbitraria. Fija un tallaje —S, M, L, XL— donde cada salto es consistente, y toda prenda sale de un peldaño conocido de esa serie. La escala de espaciado es exactamente el tallaje de los huecos de tu UI. No tienes "cualquier padding": tienes space-1, space-2, space-3, space-4…, y cada uno es un múltiplo de la misma base de 4px. Cuando un hueco se ve apretado, no inventas 17px; subes un peldaño —de space-4 (16px) a space-5 (20px)—, igual que subes de M a L.

¿Por qué 4px como base y no cualquier número? Por dos razones prácticas. La primera: 4 es pequeño, así que la escala tiene resolución —hay peldaños finos (4, 8, 12) para ajustes delicados y peldaños grandes (32, 48) para separaciones amplias—. La segunda: 4 divide bien las pantallas (que suelen medirse en múltiplos de 2 y 4), así que los espacios caen en píxeles enteros y se ven nítidos. Muchos sistemas usan base 8 (Material Design la llama "the 8-point grid") con medios pasos de 4; Tailwind usa base 4 directa (su p-4 es 4 × 0.25rem = 1rem = 16px, o sea 4 × 4px). En Mercado adoptamos base 4px, que es la de Tailwind —así la escala que construyes aquí es exactamente la que las utilidades del módulo 3 leían—.

Guarda la imagen: la escala de espaciado es el tallaje de los huecos —una base de 4px y sus múltiplos, no medidas sueltas—, y crecer un espacio es subir un peldaño, no teclear un número nuevo.

Ejemplo trabajado: space(step) sobre una base de 4px

La escala es tan simple que cabe en una función: un paso step vale step × 4px. Como el CSS suele expresarse en rem (y 1rem = 16px por defecto), damos también el rem de cada paso. La función no "elige" valores: los deriva de la base, que es justo lo que quieres —cambia la base y toda la escala se recalcula sola—.

// L2 — la escala de espaciado de Mercado: base 4px, space(step) = step * 4px.
const BASE = 4; // px — la unidad atomica de la escala

// space(step): un paso de la escala en px y en rem (1rem = 16px).
function space(step) {
  const px = step * BASE;
  return { px, rem: px / 16 };
}

console.log('=== escala de espaciado de Mercado (base 4px) ===\n');
console.log('token'.padEnd(10) + 'px'.padEnd(8) + 'rem');
console.log('-'.repeat(26));
for (const step of [1, 2, 3, 4, 5, 6, 8, 10, 12]) {
  const { px, rem } = space(step);
  console.log(('space-' + step).padEnd(10) + (px + 'px').padEnd(8) + rem + 'rem');
}

Qué esperar. Al correr el archivo con Node, la salida es exactamente esta:

=== escala de espaciado de Mercado (base 4px) ===

token     px      rem
--------------------------
space-1   4px     0.25rem
space-2   8px     0.5rem
space-3   12px    0.75rem
space-4   16px    1rem
space-5   20px    1.25rem
space-6   24px    1.5rem
space-8   32px    2rem
space-10  40px    2.5rem
space-12  48px    3rem

Lee la tabla como el tallaje completo de los huecos de Mercado. Cada fila es un peldaño, y cada valor sale de la base: space-4 = 4 × 4 = 16px, space-8 = 8 × 4 = 32px. No hay ningún número que no sea múltiplo de 4 —esa es la garantía de coherencia—. Fíjate en la columna rem: space-4 es 1rem, que es exactamente lo que p-4 te daba en el módulo 3. La utilidad p-4 no tenía magia adentro; leía el paso 4 de esta escala.

Nota también qué peldaños incluimos y cuáles no. Van del 1 al 6 seguidos —porque los espacios chicos se usan mucho y necesitas resolución fina ahí— y luego saltamos a 8, 10, 12, dejando fuera el 7, 9, 11. Es deliberado: arriba de cierto tamaño, la diferencia entre 28px y 32px casi no se percibe, así que no vale la pena tener todos los peldaños —tener menos opciones grandes te empuja a elegir de un conjunto chico y consistente—. Muchos sistemas hacen esto: pasos densos abajo, ralos arriba. Lo importante es que todos siguen siendo múltiplos de la base; la escala no se rompe, solo se vuelve más rala.

Una pregunta para pensar la escala: si necesitas un espacio de 18px para que "quepa justo", ¿qué peldaño usas? La respuesta correcta casi nunca es "agrego space-4.5". Es elegir el peldaño vecino (16 o 20) y aceptar que la coherencia vale más que ese ajuste de 2px —o, si de verdad importa, revisar si el problema es otro (un tamaño de fuente, un borde)—. La escala te limita a propósito: sus huecos son una virtud, no una carencia.

Profundización: por qué una base pequeña ordena sin que se note

El efecto de una escala de espaciado es curioso: cuando funciona, es invisible. Nadie mira una UI y piensa "qué bonitos múltiplos de 4". Lo que percibe es un ritmo —los espacios se relacionan entre sí, uno es el doble del otro, y el ojo lo lee como orden aunque no sepa por qué—. Ese ritmo es lo que distingue una interfaz "profesional" de una "hecha a las apuradas", y casi siempre es lo primero que falla cuando alguien improvisa valores: un padding de 15px aquí, uno de 18px allá, un gap de 13px —cada uno razonable por separado, pero sin relación entre sí, y el conjunto se siente "sucio"—.

Hay una segunda ventaja, más práctica: el mantenimiento. Con una escala, cambiar el "aire" general de la UI es cambiar la base. Si Mercado decidiera que todo se siente apretado, subir la base de 4px a 5px reescala todos los espacios de golpe, manteniendo sus proporciones —el que era el doble sigue siendo el doble—. Sin escala, tendrías que buscar y ajustar cada valor suelto a mano, y romperías las relaciones sin querer. La escala convierte "el espaciado de la app" en un número (la base) y una serie de peldaños, en vez de cientos de decisiones independientes.

¿Y de dónde salió que Tailwind escriba 0.25rem en vez de 4px? Es la misma escala vista en otra unidad. 4px = 0.25rem cuando 1rem = 16px. Tailwind usa rem para que los espacios respeten el tamaño de fuente base del usuario —si alguien agranda la letra de su navegador por baja visión, los espacios crecen con ella, cosa que px no haría—. Es una decisión de accesibilidad escondida en la unidad. Para nuestra escala, el px es más fácil de razonar (base 4) y el rem es lo que termina en el CSS; la función te da los dos.

La escala como ritmo (base 4px):

space-1  ▮                4px
space-2  ▮▮               8px
space-3  ▮▮▮             12px
space-4  ▮▮▮▮            16px   <- el padding tipico de una card
space-6  ▮▮▮▮▮▮          24px
space-8  ▮▮▮▮▮▮▮▮        32px
space-12 ▮▮▮▮▮▮▮▮▮▮▮▮    48px   <- separacion entre secciones

Cada barra es un multiplo de la misma base. El ojo lee la proporcion como orden.

Errores comunes

Usar valores arbitrarios fuera de la escala. Qué pasa: se escribe padding: 17px o margin: 13px porque "16 se veía apretado y 20 mucho". Por qué pasa: en el momento, un ajuste de 1px se siente inofensivo y "más preciso". Cómo detectarlo: tu CSS (o tu marcado con p-[17px]) tiene números que no son múltiplos de la base —17, 13, 15, 22—. Cómo corregirlo: elige el peldaño vecino de la escala (16 o 20) y vive con eso; la coherencia del conjunto vale infinitamente más que ese ajuste de 1px que solo tú notas. Cada valor suelto es una grieta: el próximo que edite esa pantalla no sabrá que "17" era intencional, copiará "16" o "18", y la escala se erosiona. Un sistema con diez valores fuera de escala ya no es un sistema —es CSS ad-hoc con más pasos—.

Inventar medios pasos cada vez que algo no cuadra. Qué pasa: la escala no tiene el valor exacto que quieres, así que agregas space-4.5 (18px), y luego space-2.5, y luego space-7. Por qué pasa: parece que "completar" la escala la mejora. Cómo detectarlo: tu escala tiene más peldaños que los que de verdad usas, con valores intermedios que aparecen una sola vez. Cómo corregirlo: la escala vale porque limita. Si cada vez que algo no cuadra agregas un peldaño, terminas con todos los valores posibles, y "todos los valores" es no tener escala. Antes de agregar un paso, pregunta si el peldaño vecino de verdad no sirve —casi siempre sirve—. Los pasos ralos de arriba (saltarse el 7, 9, 11) son a propósito: menos opciones, más consistencia.

Confundir la escala de espaciado con la de tamaños de fuente. Qué pasa: se usa el mismo número para un padding y para un font-size porque "es la misma escala". Por qué pasa: ambas son series de tamaños, y se ven parecidas. Cómo detectarlo: tu space-4 (16px) y tu text-base (16px) coinciden por casualidad, y empiezas a usarlos indistintamente. Cómo corregirlo: son dos escalas distintas con dos reglas distintas —el espaciado crece lineal (base × step, lección 2) y la tipografía crece geométrica (base × ratio^n, lección 3)—. Coinciden en un punto (16px) pero divergen en todos los demás: space-8 es 32px, text-xl (paso 2 tipográfico) es 25px. Mantenlas separadas; mezclarlas rompe las dos.

Ejercicios

Ejercicio 1 — Deriva el peldaño. Sin correr nada, calcula el valor en px de cada uno de estos pasos en la escala de base 4px, y di si el número que se pide pertenece a la escala:

  • (a) space-6
  • (b) space-10
  • (c) ¿14px es un peldaño de la escala?
  • (d) ¿24px es un peldaño de la escala?
Ver solución
  • (a) space-6 = 6 × 4 = 24px.
  • (b) space-10 = 10 × 4 = 40px.
  • (c) No. 14 / 4 = 3.5 —no es entero, así que 14px no es ningún space-N. Es un valor suelto; los vecinos de la escala son space-3 (12px) y space-4 (16px).
  • (d) Sí. 24 / 4 = 6, así que 24px = space-6. Pertenece a la escala.

La prueba rápida: un valor pertenece a la escala si al dividirlo entre la base (4) da un entero. 24 / 4 = 6 ✓; 14 / 4 = 3.5 ✗.

Ejercicio 2 — Predice la salida. Sin correr nada, di qué imprimiría el ejemplo trabajado si cambiáramos el bucle a estos pasos:

for (const step of [4, 8, 16]) {
Ver solución

Imprimiría tres filas, cada valor derivado de la base 4px (y su rem dividiendo entre 16):

space-4   16px    1rem
space-8   32px    2rem
space-16  64px    4rem

space-16 no estaba en la serie original (que llegaba a 12), pero la función lo deriva igual: 16 × 4 = 64px = 4rem. Esa es la ventaja de generar la escala con una fórmula en vez de una lista escrita a mano: cualquier peldaño se calcula, no se busca. (Otra cosa es si quieres exponer space-16 como token —los pasos que publicas son una decisión de diseño; los que la fórmula puede calcular son infinitos.)

Ejercicio 3 — Rediseña la base. Mercado decide que su UI se siente apretada y quiere más aire, así que cambia la base de la escala de 4px a 8px (el "8-point grid" de Material). Sin correr nada, responde: (a) ¿cuánto valdría space-4 con la nueva base? (b) ¿qué ventaja tiene haber definido la escala como step × BASE en vez de una lista de valores escritos a mano?

Ver solución
  • (a) Con BASE = 8, space-4 = 4 × 8 = 32px (antes era 16px). Todos los pasos se duplican: space-2 pasa de 8 a 16, space-6 de 24 a 48, etc.
  • (b) La ventaja es que el cambio es de un solo número. Como la escala se deriva de step × BASE, cambiar BASE de 4 a 8 recalcula toda la serie de golpe, manteniendo las proporciones (el que era el doble sigue siendo el doble). Si hubieras escrito la escala como una lista literal (space-4 = 16px, space-8 = 32px…), tendrías que editar cada valor a mano y arriesgarte a romper una relación. La fórmula convierte "el espaciado de toda la app" en un parámetro. (En la práctica, base 8 con esos saltos puede ser demasiado brusca para los espacios chicos; por eso muchos sistemas con base 8 agregan medios pasos de 4 —pero eso es afinar la escala, no abandonarla—.)

Resumen y siguiente paso

En esta lección construiste la escala de espaciado de Mercado: una base de 4px y space(step) = step × 4px, que genera la serie space-1 (4px) a space-12 (48px) sin un solo valor inventado. Con los tallajes de ropa viste por qué se hace así: los huecos de una UI no son medidas sueltas sino peldaños de una serie con salto consistente, y crecer un espacio es subir un peldaño, no teclear un número nuevo. Y lo comprobaste ejecutando: space(4) dio 16px = 1rem —exactamente el valor que p-4 te entregaba en el módulo 3—.

Antes de avanzar deberías poder: explicar por qué space-4 vale 16px; decir cómo comprobar si un valor pertenece a la escala (dividir entre la base y ver si da entero); y argumentar por qué inventar 17px erosiona el sistema.

La lección 3 construye la segunda escala de tamaño: la tipográfica. Pero esta crece distinto —no lineal (base × step) sino geométrica (base × ratio^n)—, porque el ojo percibe el tamaño de la letra en proporciones, no en sumas. Vas a ver la escala modular y por qué un ratio constante (como el salto entre notas de una octava) hace que los tamaños de texto se sientan armónicos, igual que la base de 4px hace que los espacios se sientan ordenados.

Recursos

  • Material Design, "Spacing methods" — m2.material.io/design/layout/spacing-methods.html. El "8-point grid" de Google, el sistema de espaciado más citado; míralo como una variante (base 8) de la escala que construiste. En inglés.
  • Tailwind CSS, "Padding" — tailwindcss.com/docs/padding. La escala de espaciado real de Tailwind (base 0.25rem = 4px) que este módulo toma como modelo; la fuente de los valores de p-4 del módulo 3. En inglés.
  • Nathan Curtis, "Space in Design Systems" — medium.com/eightshapes-llc/space-in-design-systems-188bcbae0d62. Un ensayo clásico sobre cómo estructurar el espaciado de un sistema; profundiza en por qué una escala ordena. En inglés.
  • web-fundamentals-html-css — módulo 2, "El box model". El prerequisito donde viste qué son padding, margin y gap; esta escala les da valores coherentes.