Actualizado 15 de julio de 2026

La trampa de la unidad vw

El titular se publicó como font-size: 8vw y se veía magnífico en el teléfono para el que se diseñó: ≈31px en una pantalla de 390px, seguro y perfectamente proporcional. La primera captura desde un monitor de oficina contó otra historia: a 1920px el mismo titular se renderizaba a ≈154px, seis palabras como un muro de tipografía, y en monitores más anchos seguía creciendo. Nada estaba roto, en el sentido de que el navegador hizo exactamente lo que se le pidió. Esa es la trampa de vw en una frase: la unidad hace exactamente una cosa, y nunca deja de hacerla.

Las unidades de viewport puras fallan como tamaños de fuente por cuatro razones mecánicas: vw no tiene límites, ignora tanto el zoom del navegador como las preferencias de tamaño de fuente (un fallo de WCAG 1.4.4), fusiona el tamaño y la tasa de crecimiento en un solo número, y cuando la tipografía y el espaciado escalan todos con el viewport, nada en la página queda anclado. La solución estándar es clamp() con una expresión rem + vw; vw puro solo se gana un lugar en texto de display a viewport completo con un suelo en rem.

Esta guía es la referencia de advertencia dentro de nuestra guía de tipografía fluida: qué sale mal, calculado en anchos reales, y la escalera de soluciones.

¿Por qué se sigue escribiendo el tamaño de fuente en vw?

Porque la seducción es real. Una sola declaración —font-size: 4vw— y el texto es perfectamente proporcional a la pantalla: sin media queries, sin niveles, sin tablas de tamaños. Un vw es el 1% del ancho del viewport (consulta la guía de web.dev sobre unidades de viewport para ver la mecánica), así que 4vw se lee como «texto que siempre es el 4% de la pantalla», que suena exactamente como lo que se suponía que era la tipografía responsive. Cada fallo de más abajo es esa misma propiedad vista desde otro ángulo: la proporcionalidad perfecta es el problema.

¿Qué se rompe con los tamaños de fuente en vw puro?

1. Sin límites. 4vw es ≈14px en un viewport de 360px y ≈77px a 1920px, ambos con la misma declaración. No hay suelo que sostenga la legibilidad en pantallas pequeñas ni techo que frene el absurdo en las grandes. Los demás fallos se pueden discutir; este es pura aritmética.

2. Sordo al zoom. El zoom del navegador escala el píxel CSS, lo que escala el texto basado en px y en rem, pero el ancho CSS del viewport se encoge por el mismo factor, así que un tamaño basado en vw se recalcula al mismo tamaño físico. Con un zoom del 200%, el texto en vw puro no crece en absoluto, y por la misma razón ignora la preferencia de tamaño de fuente del navegador. Eso incumple WCAG 1.4.4. (Toda la aritmética del zoom de rem frente a vw es un tema aparte; la versión de una línea es que solo la parte en rem de un tamaño fluido responde al zoom.)

3. Pendiente bloqueada. Con vw puro, el tamaño a cualquier ancho dado y la tasa de crecimiento son el mismo número. ¿Quieres texto de cuerpo a 16px en un teléfono de 360px? Eso es 16 / 360 × 100 ≈ 4,44vw. Pero 4,44vw sigue creciendo al mismo ritmo por cada píxel adicional de viewport, y llega a ≈85px a 1920px. No puedes decir «16px en teléfonos, y subiendo suavemente a partir de ahí»: elegir el tamaño eligió la pendiente, y la pendiente es salvaje.

4. Todo proporcional, nada anclado. La misma lógica se aplica luego al padding y a los márgenes («escalan, así que combinan»), y la página se convierte en una maqueta a escala: en cada ancho el mismo póster, fotografiado desde más cerca o más lejos. Las proporciones entre texto y espacio nunca se adaptan, la densidad de información nunca aumenta en pantallas más grandes: un monitor de escritorio muestra el diseño del teléfono, agrandado. Una página donde todo es proporcional al viewport es indistinguible de un diseño de teléfono al que se le ha hecho zoom.

¿Qué renderiza en realidad 4vw?

La tabla que lo demuestra: 4vw puro frente a un clamp acotado construido para el mismo trabajo (un encabezado de display pensado para leerse a ≈28px en teléfonos y con tope en 48px):

Viewportfont-size: 4vwclamp(1.75rem, 1.4615rem + 1.2821vw, 3rem)
320px12,8px28px (rige el mín)
360px14,4px28px
768px≈30,7px≈33,2px
1280px51,2px≈39,8px
1920px76,8px48px (rige el máx)

El punto donde las dos columnas coinciden más o menos —alrededor de los 700 y pico— es el tipo de ancho en el que 4vw «se veía bien» en el navegador de alguien durante el desarrollo. En todos los demás sitios divergen, y la columna del clamp es la que un diseñador aprobaría en cada fila.

La segunda columna, en vivo: abre una configuración fluida acotada en Scale Composer: el modo fluido se define con cuatro números (la base en vp-min, la base en vp-max, y los dos viewports), y la exportación de CSS escribe cada valor fluido como un clamp con su rango de píxeles real en un comentario: los límites que 4vw nunca tuvo, hechos explícitos.

Una configuración de tipografía fluida acotada en Scale Composer, exportada como valores clamp() con rangos de píxeles comentados

¿Cómo soluciona clamp() cada fallo?

Las soluciones se apilan, una por fallo:

  • Límites: clamp(min, …, max) restaura un suelo y un techo: los desastres de pantalla pequeña y de pantalla enorme se convierten en las dos zonas planas de la curva.
  • Zoom: la expresión preferida mezcla rem con vw. En el clamp de la tabla, la mayor parte del tamaño en el rango medio proviene del término en rem, así que el zoom alcanza a la mayoría del texto.
  • Pendiente: la ordenada y la pendiente son dos números independientes. «16px a 360px y una subida suave» ahora es expresable: el término en rem fija el ancla, el término en vw fija el ritmo.
  • Anclaje: la arquitectura de clamp en la raíz — un solo clamp fluido sobre el tamaño de fuente raíz, y todo lo demás en rem montado sobre él— escala la tipografía y el espaciado sobre una única pendiente compartida, mientras que los bordes y la geometría fina se quedan en px. La página respira; no hace zoom.

¿Cuándo son legítimas las unidades de viewport para el tamaño de fuente?

Una única excepción, dicha con precisión: texto de display a viewport completo —una línea protagonista, un número tipo póster— donde el escalado tipo póster es la verdadera intención de diseño, y solo con un suelo en rem:

font-size: max(2rem, 6vw);

El max() garantiza que el texto nunca se renderice por debajo de 2rem, y con un zoom profundo el viewport CSS que se encoge cede el control al suelo en rem, así que el texto no queda permanentemente sordo al zoom. A lo largo del rango normal sigue escalando como un póster, que aquí es justo lo que se busca. Ese intercambio es defendible para unas pocas palabras de display; es un mal intercambio para encabezados dentro de contenido corrido, y ningún intercambio en absoluto para el texto de cuerpo.

Reemplaza el número que hacía dos trabajos

Lleva la lección de la tabla a la herramienta: carga la configuración acotada y cambia un parámetro a la vez: sube la base en vp-max y observa cómo los comentarios de rango de píxeles de la exportación lo siguen mientras el suelo se mantiene quieto. Que el tamaño y la pendiente se muevan de forma independiente es toda la reparación: 4vw era un número haciendo dos trabajos, y clamp() es la degradación que necesitaba.

Seguir leyendo

  • Tipografía fluida y WCAG 1.4.4: la prueba del zoom

    La accesibilidad de la tipografía fluida depende del reparto rem/vw dentro de clamp(). Por qué el zoom necesita el término en rem, el protocolo de prueba del 200% y los números que cumplen la WCAG 1.4.4.

  • CSS clamp() explicado con números reales

    CSS clamp() explicado calculando por completo un ejemplo real — pendiente, intersección y el valor preferido vw + rem — verificado a 360px, 800px y 1280px.