Módulo 4: Scales Color And Contrast

La escala tipográfica

Descripción

El texto de una UI también viene en tamaños: el nombre del producto es más grande que el precio, el título de la sección más grande que el nombre, la letra chica del descuento más pequeña que todo. ¿De dónde salen esos tamaños? Igual que con el espaciado, la respuesta de un sistema es una escala —pero una que crece distinto—. Los tamaños de fuente no suben sumando (16, 20, 24…) sino multiplicando por un ratio constante (16, 20, 25, 31.25…), porque el ojo percibe el tamaño de la letra en proporciones, no en pasos iguales. Esa es la escala modular: base × ratio^n. En esta lección la construyes, ves la serie completa (text-sm a text-3xl), y entiendes por qué un ratio constante hace que los tamaños de texto se sientan armónicos.

Conexión con el módulo. Es la segunda escala de tamaño del módulo (la primera, el espaciado, fue la lección 2). Contrasta con ella a propósito: el espaciado crece lineal (base × step) y la tipografía crece geométrica (base × ratio^n) —dos reglas distintas para dos percepciones distintas—. Es el valor detrás de text-lg, la utilidad que usaste en el módulo 3 sin preguntar de dónde salía su tamaño. Y es una de las tres escalas que definirás en el proyecto (lección 8).

Una analogía: las notas de una octava

En música, las notas de una octava no están espaciadas por una cantidad fija de Hertz. Suben multiplicando: cada octava duplica la frecuencia (el La de una octava es 440 Hz, el de la siguiente 880, el de la siguiente 1760). Entre nota y nota dentro de la octava, la frecuencia también sube por un factor constante, no por una suma. Y el resultado suena armónico —las notas se relacionan entre sí de una forma que el oído percibe como orden—. Si en vez de multiplicar sumaras una cantidad fija de Hertz a cada nota, sonaría desafinado: las notas graves quedarían amontonadas y las agudas dispersas, porque el oído percibe el tono en proporciones, no en sumas.

La vista funciona igual con el tamaño de la letra. Una escala tipográfica que suma (16, 20, 24, 28) se ve mal: la diferencia entre 16 y 20 (un 25% más grande) se nota mucho, pero la diferencia entre 24 y 28 (un 17% más grande) se nota menos —el salto se siente cada vez más chico aunque en píxeles sea el mismo—. Una escala que multiplica (16, 20, 25, 31.25, cada una un 25% más grande que la anterior) se ve armónica: cada salto se percibe igual de grande que el anterior, porque el ojo lee la proporción, no la resta. Eso es una escala modular: eliges una base (el cuerpo de texto) y un ratio (el factor de salto), y cada tamaño es base × ratio^n.

¿Qué ratio? Los ratios comunes vienen de proporciones musicales y clásicas: 1.125 ("major second", saltos sutiles), 1.2 ("minor third"), 1.25 ("major third"), 1.333 ("perfect fourth", saltos amplios), 1.618 (el número áureo, muy dramático). Cuanto más grande el ratio, más contraste entre tamaños. En Mercado usamos 1.25 —un salto claro pero no estridente, bueno para un storefront donde el título debe destacar sin gritar—. La base es 16px, el tamaño de lectura cómodo estándar.

Guarda la imagen: la escala tipográfica es geométrica como las notas de una octava —cada tamaño multiplica al anterior por un ratio constante—, y por eso los saltos se sienten armónicos donde una escala que suma se sentiría desafinada.

Ejemplo trabajado: base × ratio^n

La escala modular es una potencia: el paso n vale base × ratio^n. El paso 0 es la base misma (ratio^0 = 1), los pasos positivos son más grandes, y los negativos —sí, existen— más chicos (text-sm es el paso −1). Redondeamos a dos decimales porque los píxeles fraccionarios reales existen pero se leen mejor así.

// L3 — la escala tipografica modular de Mercado: base * ratio^n.
const BASE = 16;    // px — el cuerpo de texto (text-base)
const RATIO = 1.25; // "major third" — el salto constante entre pasos

// step(n): el tamano del paso n, redondeado a 2 decimales (px) y en rem.
function step(n) {
  const px = BASE * Math.pow(RATIO, n);
  const round = Math.round(px * 100) / 100;
  return { px: round, rem: Math.round((round / 16) * 1000) / 1000 };
}

// nombres por rol tipografico, de mas chico a mas grande.
const names = {
  'text-sm':   -1,
  'text-base':  0,
  'text-lg':    1,
  'text-xl':    2,
  'text-2xl':   3,
  'text-3xl':   4,
};

console.log('=== escala tipografica de Mercado (base 16px, ratio 1.25) ===\n');
console.log('token'.padEnd(11) + 'n'.padEnd(4) + 'px'.padEnd(11) + 'rem');
console.log('-'.repeat(32));
for (const [name, n] of Object.entries(names)) {
  const { px, rem } = step(n);
  console.log(name.padEnd(11) + String(n).padEnd(4) + (px + 'px').padEnd(11) + rem + 'rem');
}

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

=== escala tipografica de Mercado (base 16px, ratio 1.25) ===

token      n   px         rem
--------------------------------
text-sm    -1  12.8px     0.8rem
text-base  0   16px       1rem
text-lg    1   20px       1.25rem
text-xl    2   25px       1.563rem
text-2xl   3   31.25px    1.953rem
text-3xl   4   39.06px    2.441rem

Lee la tabla como la escala de letras de Mercado. text-base (paso 0) es la base, 16px —el cuerpo de texto de la tarjeta—. text-lg (paso 1) es 16 × 1.25 = 20px —el nombre del producto—. text-2xl (paso 3) es 16 × 1.25³ = 31.25px —un título de sección—. Y text-sm (paso −1) es 16 / 1.25 = 12.8px —la letra chica del descuento—. Cada uno es la base multiplicada por el ratio elevado a su paso; ningún tamaño es inventado.

Comprueba tú mismo el ratio constante: 20 / 16 = 1.25, 25 / 20 = 1.25, 31.25 / 25 = 1.25. Cada tamaño es exactamente 1.25 veces el anterior. Esa es la razón de que la escala se sienta armónica —el salto proporcional es idéntico en todos los peldaños, aunque en píxeles crezca (de 16 a 20 son 4px, de 25 a 31.25 son 6.25px)—. El ojo lee la proporción, y la proporción es constante.

Una advertencia honesta sobre un detalle que quizás notaste desde el módulo 3. Allá, text-lg valía 1.125rem (18px), no 1.25rem (20px) como aquí. No es una contradicción: es que Tailwind no usa una escala modular estricta —sus tamaños por defecto (12, 14, 16, 18, 20, 24…) están afinados a mano, no generados por un ratio único—. Las dos filosofías son válidas: una escala modular pura (la que construimos, matemáticamente coherente) o una escala afinada a mano (la de Tailwind, ajustada para que ciertos tamaños comunes caigan en números "redondos"). Mercado adopta la modular por su coherencia; si prefirieras las de Tailwind, las declararías en theme.fontSize (módulo 3). Lo que no debes hacer es mezclar: elige una filosofía y sé consistente. Lo que importa del módulo es entender que los tamaños salen de una regla, sea el ratio o la lista afinada.

Una pregunta para pensar la escala: text-2xl da 31.25px, un valor con decimales. ¿Es un problema? (No: los navegadores renderizan tamaños de fuente fraccionarios sin drama —redondean al subpíxel más cercano—. El decimal es la señal de que el valor salió de un ratio, no de que alguien tecleó "31.25". Si te molesta, puedes redondear los tamaños grandes a enteros al publicarlos como tokens, aceptando que ya no serán exactamente base × ratio^n —otra vez la tensión entre pureza matemática y números redondos—.)

Profundización: por qué positivos y negativos, y qué ratio elegir

La escala modular tiene una elegancia que la lineal no: crece y decrece con la misma regla. El paso 0 es tu base de lectura, los positivos son títulos (cada vez más grandes), y los negativos son texto secundario (text-sm a −1, y podrías tener un text-xs a −2, que daría 16 / 1.25² = 10.24px). No necesitas dos reglas (una para agrandar, otra para achicar): una sola potencia cubre todo el rango, y todo se relaciona con la base por un factor de ratio^n. Esa unidad es parte de por qué la escala se siente coherente de la letra más chica a la más grande.

La elección del ratio es la decisión de diseño más importante de la escala, porque fija cuánto contraste hay entre tus tamaños. Un ratio chico (1.125) da una escala densa y sutil —buena para interfaces con mucha información, donde no quieres que los títulos dominen—. Un ratio grande (1.333 o el áureo 1.618) da una escala dramática —buena para una landing page donde el título debe ser lo primero que ves—. El 1.25 de Mercado está en el medio: los títulos destacan con claridad sin aplastar al cuerpo de texto, apropiado para un storefront donde el producto (no el título) es el protagonista.

Lineal (suma) vs modular (multiplica), desde 16px:

           16   20   24   28   32   36        (lineal +4: saltos que "se sienten" menores al crecer)
           |    |    |    |    |    |
           16   20   25   31   39   49        (modular x1.25: cada salto es 25%, se siente igual)
           |    |     |     |      |      |
                                             
El ojo lee proporcion. El salto lineal 16->20 (25%) se nota;
el salto lineal 32->36 (12.5%) casi no. El modular mantiene 25% siempre.

Hay un detalle que la escala modular no resuelve y conviene nombrar: la escala te da el font-size, pero el texto legible necesita también un line-height (interlineado) coherente. La convención es que el interlineado también escale —texto chico lleva interlineado proporcionalmente mayor para respirar, texto grande (títulos) interlineado más ajustado—. Tailwind, por eso, empareja cada text-* con un line-height (viste ese par en el módulo 3: text-lg traía font-size: 1.125rem; line-height: 1.75rem). Construir la escala de interlineado con su propia regla es una extensión natural de esta lección; aquí nos quedamos en el font-size, que es el eje principal.

Errores comunes

Usar una escala lineal para el texto. Qué pasa: se definen los tamaños sumando (16, 20, 24, 28, 32), como si fuera la escala de espaciado. Por qué pasa: la escala lineal es más intuitiva (los números son "redondos") y uno no sabe que la vista pide proporción. Cómo detectarlo: tus saltos de tamaño se sienten desparejos —los títulos grandes parecen "no lo suficientemente grandes" comparados con el salto que dio el cuerpo—. Cómo corregirlo: usa una escala geométrica (base × ratio^n). El espaciado suma porque el ojo percibe la distancia en píxeles; la tipografía multiplica porque el ojo percibe el tamaño en proporción. Son dos reglas distintas a propósito —esa es justo la lección que contrasta la 2 con la 3—.

Inventar tamaños fuera de la escala. Qué pasa: se necesita un título "un poco más grande que text-lg pero no tanto como text-xl" y se escribe font-size: 22px. Por qué pasa: 22 cae en el hueco entre 20 y 25, y parece razonable. Cómo detectarlo: tu CSS tiene tamaños de fuente que no son 16 × 1.25^n para ningún n —21, 22, 17—. Cómo corregirlo: es el mismo error que 17px en el espaciado, vestido de tipografía. Elige el peldaño de la escala (20 o 25); si de verdad ninguno sirve, quizás el problema es el ratio (demasiado grande el salto) y conviene revisar la escala entera, no parchear un tamaño. Un tamaño suelto rompe la armonía proporcional tanto como un espacio suelto rompe el ritmo.

Elegir un ratio dramático sin querer. Qué pasa: se copia un ratio de 1.5 o 1.618 de un ejemplo de landing page y se aplica a un dashboard lleno de datos, y los títulos quedan enormes y desproporcionados. Por qué pasa: el ratio se copia sin pensar qué tipo de interfaz es. Cómo detectarlo: text-2xl da un tamaño que domina la pantalla y deja poco aire para el contenido. Cómo corregirlo: el ratio es una decisión de diseño ligada al contexto —interfaces densas piden ratios chicos (1.125–1.2), landings piden ratios grandes (1.333+)—. Mercado, un storefront donde el producto manda, usa 1.25. No hay un ratio "correcto" universal; hay uno correcto para tu interfaz. Prueba dos o tres (type-scale.com te deja verlos en vivo) y elige el que deje el contraste que tu contenido necesita.

Ejercicios

Ejercicio 1 — Deriva el paso. Con base 16 y ratio 1.25, calcula (puedes redondear a 2 decimales) el tamaño de:

  • (a) text-xl (paso 2)
  • (b) text-xs (paso −2)
  • (c) El paso 5 (text-4xl)
Ver solución
  • (a) text-xl = 16 × 1.25² = 16 × 1.5625 = 25px.
  • (b) text-xs = 16 × 1.25⁻² = 16 / 1.5625 = 10.24px.
  • (c) text-4xl = 16 × 1.25⁵ = 16 × 3.0518 = 48.83px (redondeado).

La clave: el exponente es el paso. Positivo agranda, negativo achica, cero es la base. Cada paso multiplica (o divide) por el ratio otra vez.

Ejercicio 2 — Predice la salida. Sin correr nada, di qué imprimiría el ejemplo trabajado si cambiáramos el ratio a 1.5 (dejando la base en 16 y los mismos nombres). Da los valores de text-base, text-lg y text-xl.

Ver solución

Con RATIO = 1.5:

text-base  0   16px       1rem
text-lg    1   24px       1.5rem
text-xl    2   36px       2.25rem

text-base no cambia (paso 0, ratio^0 = 1 siempre). Pero los saltos son mucho más grandes: text-lg = 16 × 1.5 = 24 (antes 20), text-xl = 16 × 1.5² = 36 (antes 25). Un ratio de 1.5 es dramático —los títulos crecen rápido—, apropiado para una landing, probablemente demasiado para un storefront denso. Este ejercicio muestra en números por qué el ratio es la decisión de la escala: un cambio de 1.25 a 1.5 transforma el carácter de toda la tipografía.

Ejercicio 3 — Lineal vs modular. Un compañero propone la escala de tamaños 16, 20, 24, 28, 32 (sumando 4). Sin correr nada, responde: (a) ¿qué regla usa? (b) ¿por qué se vería peor que la modular a medida que los tamaños crecen? (c) ¿en qué se diferencia esto de la escala de espaciado, que sí suma?

Ver solución
  • (a) Es una escala lineal: cada paso suma una constante (4px). No hay ratio; hay una diferencia fija.
  • (b) Porque el salto proporcional se achica al crecer. De 16 a 20 es +25%; de 28 a 32 es solo +14%. El ojo percibe proporción, así que los saltos entre los tamaños grandes "se sienten" cada vez menores, y la escala pierde contraste arriba —justo donde los títulos deberían destacar—. La modular mantiene +25% en todos los pasos, así que el contraste es parejo.
  • (c) El espaciado suma porque el ojo percibe la distancia entre elementos en píxeles absolutos —un hueco de 32px se ve el doble que uno de 16px, y eso es lo que quieres—. La tipografía multiplica porque el ojo percibe el tamaño de la letra en proporción. Son dos percepciones distintas, y por eso dos reglas distintas. No es incoherencia: es cada escala usando la regla que su percepción pide.

Resumen y siguiente paso

En esta lección construiste la escala tipográfica de Mercado: una escala modular con base 16px y ratio 1.25, donde cada tamaño es base × ratio^n. Con las notas de una octava viste por qué crece geométrica y no lineal: el ojo percibe el tamaño de la letra en proporciones, así que un ratio constante hace los saltos armónicos donde una suma constante los haría desafinados. Y lo comprobaste ejecutando: la serie text-sm (12.8px) a text-3xl (39.06px) salió del ratio, con cada tamaño exactamente 1.25 veces el anterior.

Antes de avanzar deberías poder: explicar por qué la tipografía usa una escala geométrica y el espaciado una lineal; calcular cualquier paso como base × ratio^n; y decir qué controla el ratio (el contraste entre tamaños) y cómo elegirlo según el tipo de interfaz.

Con las dos escalas de tamaño construidas, la lección 4 pasa al color —que escala distinto, porque tiene dos ejes (tono y claridad)—. Vas a ver una paleta como una rampa de un tono en steps de claridad (50 casi blanco, 900 casi negro), la anatomía de las rampas de Tailwind y Material, y por qué numerar la claridad en steps prepara el terreno para lo que viene después: medir el contraste entre dos colores, que es, en el fondo, medir la distancia entre sus claridades.

Recursos

  • Type Scale — type-scale.com. Una herramienta que genera la escala modular en vivo: cambia la base y el ratio y ve la serie; el laboratorio de esta lección. En inglés.
  • Tailwind CSS, "Font Size" — tailwindcss.com/docs/font-size. La escala tipográfica real de Tailwind (afinada a mano, con su line-height emparejado); el contraste con la modular pura que construiste. En inglés.
  • "More Meaningful Typography" (A List Apart) — alistapart.com/article/more-meaningful-typography. El artículo clásico de Tim Brown que popularizó la escala modular basada en ratios musicales; el fundamento de la analogía de la octava. En inglés.
  • web-fundamentals-html-css — módulo 4, "Tipografía en CSS". El prerequisito donde viste font-size, line-height y las unidades rem/em; esta escala les da valores coherentes.