Tokens

Spacing fluido

El spacing de FDS convierte una pequena configuracion de variables en una escala fluida completa. El objetivo es que el ritmo vertical, los gaps, el padding de secciones y los espacios internos crezcan de forma proporcional entre mobile y desktop sin escribir media queries.

El sistema tiene 4 niveles:

  1. Rango de viewport.
  2. Knobs editables.
  3. Escala fluida derivada.
  4. Tokens semanticos para usar en clases Tailwind.

Configuracion fluida

La interpolacion ocurre entre --viewport-min y --viewport-max, definidos en theme/flowtitude.css:

--viewport-min: 410px;
--viewport-max: 1280px;

FDS calcula un progreso fluido (--ft-fluid-t) con el ancho real del viewport:

--ft-fluid-t: calc(
  (100vw - var(--viewport-min)) /
  (var(--viewport-max) - var(--viewport-min))
);

Ese progreso alimenta los clamp() del espacio base y del ratio de escala:

--ft-space-min: 0.5rem;      /* Espacio base en viewport minimo */
--ft-space-max: 1.5rem;      /* Espacio base en viewport maximo */
--ft-space-step-min: 1.3;    /* Ratio de escala minimo */
--ft-space-step-max: 1.5;    /* Ratio de escala maximo */
--ft-space-factor: 1;        /* Multiplicador global */
--ft-space-value: clamp(
  var(--ft-space-min),
  calc(var(--ft-space-min) + (var(--ft-space-max) - var(--ft-space-min)) * var(--ft-fluid-t)),
  var(--ft-space-max)
);

--ft-space-step: clamp(
  var(--ft-space-step-min),
  calc(var(--ft-space-step-min) + (var(--ft-space-step-max) - var(--ft-space-step-min)) * var(--ft-fluid-t)),
  var(--ft-space-step-max)
);

Por debajo de 410px, el sistema usa el minimo. Por encima de 1280px, usa el maximo. Entre ambos, interpola de forma continua.

clamp() es la pieza importante: pone limite minimo, valor fluido intermedio y limite maximo en una sola declaracion. Por eso el sistema no necesita media queries para este comportamiento.

clamp(valor-minimo, valor-fluido, valor-maximo)

Fallback de compatibilidad

FDS no deja los tokens principales dependiendo solo de calc() o clamp(). La configuracion actual usa tres niveles:

NivelCuando se usaResultado
Fallback baseNavegadores con variables CSS pero sin CSS math fiableValores estaticos mobile
Fallback desktop@media (min-width: 1280px)Valores estaticos desktop
Mejora fluida@supports confirma clamp(), calc(), division y math anidadoTokens fluidos completos

Esto significa que navegadores antiguos no obtienen interpolacion fluida, pero si mantienen una escala valida de spacing. Los navegadores modernos siguen usando los knobs y derivados fluidos.

@supports (font-size: calc(clamp(1rem, 2vw, 2rem) * 1)) and
  (padding-top: calc(1rem / 2)) {
  :root {
    --spacing-block: calc(var(--spacing-fluid-md) * var(--ft-space-factor-block));
  }
}

Escala de spacing

La escala fluid-* se deriva del espacio base (--spacing-fluid-md). Los pasos pequenos dividen por el ratio; los grandes multiplican por el ratio.

--spacing-fluid-md:  calc(var(--ft-space-value) * var(--ft-space-factor));
--spacing-fluid-sm:  calc(var(--spacing-fluid-md) / var(--ft-space-step));
--spacing-fluid-xs:  calc(var(--spacing-fluid-sm) / var(--ft-space-step));
--spacing-fluid-lg:  calc(var(--spacing-fluid-md) * var(--ft-space-step));
--spacing-fluid-xl:  calc(var(--spacing-fluid-lg) * var(--ft-space-step));
--spacing-fluid-2xl: calc(var(--spacing-fluid-xl) * var(--ft-space-step));
TokenRelacionUso directo
fluid-xsMuy pequenoAjustes finos, separaciones internas minimas
fluid-smPequenoGaps discretos, grupos compactos
fluid-mdBaseRitmo normal de UI
fluid-lgGrandeBloques internos amplios
fluid-xlMuy grandeSeparacion fuerte entre grupos
fluid-2xlExtra grandeBase para heroes y espacios de alto impacto

Los tokens fluid-* son utiles cuando necesitas precision tecnica. Para construir paginas y secciones, normalmente conviene usar los tokens semanticos.

Formula mental

fluid-md es el punto medio del sistema. Hacia abajo, FDS divide por --ft-space-step; hacia arriba, multiplica por --ft-space-step. El propio step tambien es fluido, asi que la escala se comprime en mobile y se abre en desktop.


Spacing semantico

Los tokens semanticos son una capa de lenguaje encima de la escala fluida. No dicen "cuanto mide" un espacio; dicen "para que sirve".

Los multiplicadores tambien son knobs editables:

--ft-space-factor-inner: 0.5;
--ft-space-factor-content: 0.75;
--ft-space-factor-stack: 1;
--ft-space-factor-block: 1;
--ft-space-factor-columns: 1.5;
--ft-space-factor-section: 3;
--ft-space-factor-hero: 4.5;

Y generan los tokens finales:

--spacing-inner:   calc(var(--spacing-fluid-xs) * var(--ft-space-factor-inner));
--spacing-content: calc(var(--spacing-fluid-sm) * var(--ft-space-factor-content));
--spacing-stack:   calc(var(--spacing-fluid-sm) * var(--ft-space-factor-stack));
--spacing-block:   calc(var(--spacing-fluid-md) * var(--ft-space-factor-block));
--spacing-columns: calc(var(--spacing-fluid-md) * var(--ft-space-factor-columns));
--spacing-section: calc(var(--spacing-fluid-xl) * var(--ft-space-factor-section));
--spacing-hero:    calc(var(--spacing-fluid-2xl) * var(--ft-space-factor-hero));
TokenFactor inicialUso tipico
inner0.5Padding interno muy ajustado: badges, botones pequenos, chips
content0.75Gaps entre elementos de contenido cercano
stack1Separacion vertical repetida entre items
block1Distancia entre bloques dentro de una seccion
columns1.5Gaps entre columnas, cards o grupos paralelos
section3Padding vertical principal de secciones
hero4.5Espacio de heroes o pantallas de maxima presencia

Valores aproximados

Con la configuracion actual, estos son los rangos aproximados entre 410px y 1280px. No son valores que haya que memorizar; sirven para entender el orden de magnitud de cada token.

TokenMobile aprox.Desktop aprox.Uso
inner0.15rem0.33remPadding interno minimo
content0.29rem0.75remGaps pequenos de contenido
stack0.38rem1remApilar elementos
block0.5rem1.5remBloques de contenido
columns0.75rem2.25remColumnas y grids
section2.54rem10.13remPadding vertical principal
hero4.94rem22.78remHeroes y pantallas especiales

Si estos valores parecen demasiado comprimidos o demasiado amplios, normalmente se ajusta antes --ft-space-min, --ft-space-max o los multiplicadores semanticos que las clases en el markup.


Uso en Tailwind

Como estos tokens se declaran en @theme con el prefijo --spacing-*, Tailwind v4 genera utilidades de spacing con esos nombres.

<div class="grid gap-columns p-section">
  <article class="p-block">
    <h2 class="mb-content">Titulo</h2>
    <p>Contenido...</p>
  </article>

  <article class="space-y-stack">
    <p>Item 1</p>
    <p>Item 2</p>
  </article>
</div>

Puedes usar los mismos sufijos con las familias habituales de Tailwind:

FamiliaEjemplos
Paddingp-inner, px-content, py-section, pt-hero
Marginm-block, mt-section, mb-content, mx-auto
Gapgap-content, gap-block, gap-columns
Spacespace-y-stack, space-x-content
Sizew-block, h-fluid-lg, size-inner

Preferencia de uso

En layouts y componentes compartidos, usa nombres semanticos (gap-content, p-block, py-section). Reserva fluid-xs a fluid-2xl para casos donde necesitas expresar un paso tecnico de la escala.


Uso directo en CSS

Tambien puedes usar las variables directamente cuando estas escribiendo un componente propio dentro de una layer:

@layer components {
  .feature-card {
    padding: var(--spacing-block);
    gap: var(--spacing-content);
    border-radius: var(--radius-card);
  }

  .feature-card + .feature-card {
    margin-top: var(--spacing-stack);
  }
}

En markup de WordPress o Bricks suele ser mas comodo usar clases (p-block, gap-content). En CSS de componentes compartidos, usar var(--spacing-*) deja claro que el componente depende del sistema semantico.


Que knob tocar

NecesidadVariable
Todo el spacing se siente pequeno o grande--ft-space-factor
El mobile necesita mas o menos aire--ft-space-min
El desktop necesita mas o menos aire--ft-space-max
La escala entre pasos es demasiado plana o exagerada en mobile--ft-space-step-min
La escala entre pasos es demasiado plana o exagerada en desktop--ft-space-step-max
Solo un significado esta mal calibrado--ft-space-factor-inner a --ft-space-factor-hero
Las secciones deben respirar mas o menos--ft-padding-content-y, --ft-padding-content-y-half o --ft-space-factor-section
El gap interno del contenedor de seccion debe cambiar--ft-gap-content

Orden recomendado

Primero ajusta los knobs globales si toda la escala esta desplazada. Despues ajusta multiplicadores semanticos si solo falla un tipo de espacio. Cambia clases en el markup solo cuando el problema es local de una composicion concreta.


Andamiaje de secciones

Las secciones de FDS usan los tokens semanticos como configuracion por defecto:

--ft-padding-content-y: var(--spacing-section);
--ft-padding-content-y-half: 1.2675rem; /* fallback; en moderno se calcula desde --ft-padding-content-y */
--ft-gap-content: var(--spacing-block);

layouts/section.css aplica esa configuracion al elemento section y a su hijo directo:

section {
  @apply w-full px-[var(--ft-padding-content-x)];
  padding-top: var(--ft-padding-content-y-half);
  padding-bottom: var(--ft-padding-content-y-half);
}

section > div {
  @apply mx-auto w-full max-w-[var(--ft-container)] flex flex-col gap-[var(--ft-gap-content)];
}

En navegadores modernos, la media seccion exacta se activa desde la capa de tokens:

@supports (padding-top: calc(1rem / 2)) {
  :root {
    --ft-padding-content-y-half: calc(var(--ft-padding-content-y) / 2);
  }
}

Esto significa que una seccion basica ya tiene:

ElementoEspacio aplicado
sectionPadding horizontal global y medio padding vertical
section > divContenedor centrado, ancho maximo y gap-block via --ft-gap-content
section.has-backgroundPadding vertical completo
Primera/ultima seccionPadding top/bottom completo para cerrar bien la pagina
.half-top / .half-bottomMitad del padding en el lado indicado

Prose y ritmo editorial

.prose pertenece a la capa base y define el ritmo de contenido editorial: titulos, parrafos, listas, citas y tablas dentro de un wrapper.

<article class="prose">
  <h2>Titulo de contenido</h2>
  <p>Primer parrafo editorial.</p>
  <p>Segundo parrafo con ritmo automatico.</p>
  <ul>
    <li>Elemento de lista</li>
    <li>Elemento de lista</li>
  </ul>
</article>

El sistema de spacing semantico se usa sobre todo en layouts manuales (gap-content, p-block, py-section). .prose resuelve el ritmo interno del contenido largo con reglas base anidadas. Es una capa distinta: no necesitas poner mb-content en cada parrafo de un articulo.


Pagina de auditoria copiable

Copia este bloque en una pagina de prueba con FDS activo. Sirve para revisar de un vistazo como cambian la escala fluida, los espacios semanticos, los gaps, los paddings y el ritmo de .prose cuando modificas variables en theme/flowtitude.css.

<main>
  <section class="has-background bg-secondary-50 text-secondary-950">
    <div>
      <header class="content-flex top-left max-w-4xl">
        <span class="eyebrow">Auditoria FDS</span>
        <h1 class="display-sm">Mapa visual del spacing fluido</h1>
        <p class="text-large">
          Cambia los knobs de spacing y revisa como se recalculan las barras,
          paddings, gaps, secciones y contenido editorial.
        </p>
      </header>

      <div class="grid gap-columns lg:grid-cols-2">
        <article class="rounded-card border border-secondary-200 bg-white p-block">
          <h2 class="heading-sm mb-content">Escala fluid-*</h2>
          <div class="space-y-stack">
            <div class="grid grid-cols-[9rem_1fr] items-center gap-content">
              <code>h-fluid-xs</code>
              <div class="h-fluid-xs bg-primary-500"></div>
            </div>
            <div class="grid grid-cols-[9rem_1fr] items-center gap-content">
              <code>h-fluid-sm</code>
              <div class="h-fluid-sm bg-primary-500"></div>
            </div>
            <div class="grid grid-cols-[9rem_1fr] items-center gap-content">
              <code>h-fluid-md</code>
              <div class="h-fluid-md bg-primary-500"></div>
            </div>
            <div class="grid grid-cols-[9rem_1fr] items-center gap-content">
              <code>h-fluid-lg</code>
              <div class="h-fluid-lg bg-primary-500"></div>
            </div>
            <div class="grid grid-cols-[9rem_1fr] items-center gap-content">
              <code>h-fluid-xl</code>
              <div class="h-fluid-xl bg-primary-500"></div>
            </div>
            <div class="grid grid-cols-[9rem_1fr] items-center gap-content">
              <code>h-fluid-2xl</code>
              <div class="h-fluid-2xl bg-primary-500"></div>
            </div>
          </div>
        </article>

        <article class="rounded-card border border-secondary-200 bg-white p-block">
          <h2 class="heading-sm mb-content">Tokens semanticos</h2>
          <div class="space-y-stack">
            <div class="p-inner border border-secondary-200">
              <code>p-inner</code>
            </div>
            <div class="p-content border border-secondary-200">
              <code>p-content</code>
            </div>
            <div class="p-stack border border-secondary-200">
              <code>p-stack</code>
            </div>
            <div class="p-block border border-secondary-200">
              <code>p-block</code>
            </div>
            <div class="p-columns border border-secondary-200">
              <code>p-columns</code>
            </div>
          </div>
        </article>
      </div>

      <article class="rounded-card border border-secondary-200 bg-white p-block">
        <h2 class="heading-sm mb-content">Gaps comparados</h2>
        <div class="grid gap-columns md:grid-cols-3">
          <div>
            <h3 class="subheading-sm mb-content">gap-content</h3>
            <div class="grid gap-content">
              <div class="bg-secondary-100 p-content">Item</div>
              <div class="bg-secondary-100 p-content">Item</div>
              <div class="bg-secondary-100 p-content">Item</div>
            </div>
          </div>

          <div>
            <h3 class="subheading-sm mb-content">gap-block</h3>
            <div class="grid gap-block">
              <div class="bg-secondary-100 p-content">Item</div>
              <div class="bg-secondary-100 p-content">Item</div>
              <div class="bg-secondary-100 p-content">Item</div>
            </div>
          </div>

          <div>
            <h3 class="subheading-sm mb-content">gap-columns</h3>
            <div class="grid gap-columns">
              <div class="bg-secondary-100 p-content">Item</div>
              <div class="bg-secondary-100 p-content">Item</div>
              <div class="bg-secondary-100 p-content">Item</div>
            </div>
          </div>
        </div>
      </article>

      <article class="rounded-card border border-secondary-200 bg-white p-block">
        <h2 class="heading-sm mb-content">Padding de seccion</h2>
        <div class="space-y-stack">
          <div class="bg-secondary-100 px-content py-section">
            <code>py-section</code>
          </div>
          <div class="bg-secondary-200 px-content py-hero">
            <code>py-hero</code>
          </div>
        </div>
      </article>

      <div class="grid gap-columns lg:grid-cols-2">
        <article class="rounded-card border border-secondary-200 bg-white p-block">
          <h2 class="heading-sm mb-content">Ritmo manual</h2>
          <div class="space-y-stack">
            <p class="text-medium">
              Este bloque usa <code>space-y-stack</code> para separar items
              disenados a mano.
            </p>
            <p class="text-medium">
              Es el patron recomendado para composiciones controladas.
            </p>
            <a class="btn btn-primary" href="#">Boton con spacing interno</a>
          </div>
        </article>

        <article class="prose rounded-card border border-secondary-200 bg-white p-block">
          <h2>Ritmo prose</h2>
          <p>
            Este bloque usa <code>prose</code>. Los parrafos, enlaces, listas y
            titulos reciben ritmo editorial desde la capa base.
          </p>
          <p>
            No hace falta asignar <code>mb-content</code> a cada parrafo.
          </p>
          <ul>
            <li>Lista generada desde contenido largo.</li>
            <li>Segundo item con ritmo interno automatico.</li>
          </ul>
        </article>
      </div>
    </div>
  </section>
</main>
Previous
Tipografia fluida