ADR: Toggle "Tamaño global" — override de variables --text-* de Tailwind v4 en scope body (s56 round 3)
Contexto
El panel de preferencias de usuario (/prefs) expone un toggle “Tamaño global” con cuatro niveles (sm | md | lg | xl). El objetivo es que el usuario pueda ampliar o reducir la tipografía de la aplicación sin alterar el espaciado, los tamaños de layout ni los márgenes.
La implementación correcta requirió tres iteraciones en la sesión s56 (11-05-2026) antes de llegar a un diseño estable.
Problema original
Tailwind v4 genera sus utility classes text-xs, text-sm, text-base, text-lg, text-xl usando custom properties CSS internas (--text-xs, --text-sm, etc.) que no dependen del font-size del <body> sino del root <html>. Adicionalmente, padding, gap, margin y width/height también se expresan en rem, calculados desde html { font-size }.
Iteraciones (historial)
Round 1 — solo body[data-font-size]
body[data-font-size="sm"] { font-size: 0.85rem; }
Resultado: no funcionaba. Las utility classes Tailwind usaban rem desde <html>, ignorando el font-size del <body>. Los componentes Tasks, Notes, KanbanMini no escalaban.
Round 2 — html[data-font-size] + body[data-font-size]
html[data-font-size="sm"] { font-size: 13.5px; }
body[data-font-size="sm"] { font-size: 0.85rem; }
prefs.ts:applyPrefsToBody también aplicaba el atributo al <html>.
Resultado: funcionaba para tipografía, pero todo lo expresado en rem escalaba (padding, gap, border-radius, iconos, layouts) → el toggle se convertía en un zoom de página completo, no en un toggle tipográfico.
Round 3 — override de --text-* en scope body ✅ (solución definitiva)
Se revirtió el setAttribute sobre <html> en prefs.ts. Solo el <body> recibe data-font-size. En globals.css se sobreescriben las custom properties que Tailwind usa internamente para las utility classes de texto:
body[data-font-size="sm"] {
--text-xs: 0.7rem;
--text-sm: 0.8125rem;
--text-base: 0.9375rem;
--text-lg: 1.05rem;
--text-xl: 1.2rem;
font-size: 0.85rem; /* legado — componentes sin class Tailwind */
}
/* ídem para md (defaults Tailwind), lg y xl */
Resultado: las utility classes text-sm, text-base, etc. recogen el override. padding, gap y demás rem permanecen invariantes porque el font-size del <html> no cambia.
Decisión adoptada
No modificar nunca el
font-sizedel elemento<html>para cambiar el tamaño tipográfico de preferencias. Hacerlo actúa como un zoom de página completo porque Tailwind v4 usarempara todo el sistema de espaciado.La técnica correcta es redefinir las custom properties
--text-*dentro del scopebody[data-font-size="<nivel>"].
Consecuencia: los literales rem no responden
Componentes que usen fontSize: '0.875rem' como literal hardcoded (inline style) no responden al toggle. Para que un componente responda al toggle de tamaño, debe usar fontSize: 'var(--text-sm)' (o la utility class Tailwind equivalente).
Como parte de este fix se migraron los literales de KanbanMini.tsx:
| Antes | Después |
|---|---|
'0.875rem' | 'var(--text-sm)' |
'0.84rem' | 'var(--text-sm)' |
'0.97rem' | 'var(--text-base)' |
'0.94rem' | 'var(--text-base)' |
Archivos clave
| Archivo | Rol |
|---|---|
src/lib/prefs.ts → applyPrefsToBody() | Aplica data-font-size solo al <body>, NO al <html> |
src/styles/globals.css → sección FONT SIZE | Define los cuatro bloques body[data-font-size="*"] con override de --text-* |
src/components/widgets/KanbanMini.tsx | Ejemplo de componente migrado a var(--text-*) |
Regla de desarrollo
Cualquier nuevo componente que deba respetar el toggle “Tamaño global” debe usar
var(--text-xs|sm|base|lg|xl)en sus estilos inline, o la utility class Tailwind equivalente (text-sm,text-base…). Nunca valoresremliterales.
Véase también
- [[crearack—conceptos—interfaz-general]]
- [[workspace—que-es-workspace]]