Tipografía que crece: tamaños responsivos sin saltos
En una tableta, el título dentro de una tarjeta se veía casi tan grande como el título de sección encima. La culpa era de los píxeles fijos y dos media queries. Cómo reconstruimos nuestro propio sitio con rem y clamp(), con los valores medidos antes y después.
Rara vez se nota mientras construyes. Se nota después, cuando alguien abre el sitio en una tableta. El título encima de una tarjeta aparece casi tan grande como el título de sección que tiene arriba. En el móvil, la línea pequeña sobre un título queda de pronto casi a la misma altura que él. En el ordenador todo cuadra.
Eso es exactamente lo que teníamos en este sitio. Medido a 1440, 900 y 375 píxeles de ancho de ventana:
| Elemento | Ordenador | Tableta | Móvil |
|---|---|---|---|
| Título de entrada | 66 px | 44 px | 34 px |
| Título de sección | 46 px | 38 px | 30 px |
| Título dentro de una tarjeta | 32 px | 32 px | 26 px |
| Línea sobre el título de sección | 17 px | 17 px | 17 px |
El error está en la última fila. La línea pequeña sobre un título, en nuestro sitio dice "Proyectos de clientes", medía 17 píxeles a cualquier ancho. El título de al lado bajaba de 46 a 30. En el ordenador, uno era 2,7 veces el otro; en el móvil, solo 1,8 veces. La mitad de la distancia que distingue una etiqueta de un título había desaparecido.
La tercera fila es el mismo error en la otra dirección: el título de la tarjeta se quedaba en 32 píxeles mientras el título de sección de encima bajaba a 38. A 768 píxeles de ancho los dos quedaban casi a la par, aunque uno está subordinado al otro.
Por qué pasa
Dos costumbres juntas lo producen sin fallo.
Todo está en píxeles. En nuestro sitio eran 183 declaraciones, todas en px, ninguna en rem, ninguna en clamp().
El tamaño cambia en las media queries. En nuestro caso en dos, 1100 y 720 píxeles. Entre salto y salto no pasa nada.
La consecuencia es que cada título necesita sus escalones uno por uno: uno para el ordenador, otro a partir de 1100, otro a partir de 720. Si olvidas uno no te enteras, porque la página no se ve rota. Solo se ve mal a un ancho que no sueles tener abierto. A nosotros nos faltaban los escalones en la tarjeta y en la etiqueta, y fueron justo esos dos los que se notaron.
Cuál es hoy la buena práctica
La versión corta, y de verdad es así de corta:
remcomo medida base. Así la letra sigue el ajuste del navegador.clamp()para todo lo que sea grande. Así crece de forma continua con el ancho de la ventana en vez de saltar.vwsolo como término intermedio, nunca solo. El suelo y el techo van enrem.
El tercer punto es el que más se hace mal, así que va primero.
Por qué el vw puro no sirve
font-size: 4vw suena a la solución más sencilla para una tipografía fluida. Pero no es accesible, y el motivo resulta incómodamente elegante:
Cuando alguien amplía una página al 200 por ciento, se agranda el píxel CSS. Una ventana que antes medía 1400 píxeles CSS de ancho mide 700 después. Y 4vw de 700 es exactamente la mitad de 4vw de 1400.
La ampliación y la reducción se anulan con precisión. Tras el zoom, el texto queda igual de grande que antes. Quien amplía porque ve mal no ha ganado nada. Eso incumple el criterio 1.4.4 de las WCAG, que exige que el texto pueda ampliarse al 200 por ciento sin perder contenido.
Dentro de clamp(), en cambio, vw es inofensivo mientras el suelo y el techo estén en rem: al hacer zoom esos dos crecen, y la letra aterriza en el suelo en vez de en la nada.
Por qué px ignora el ajuste del navegador
El segundo punto, que se escapa con facilidad: font-size: 17px son 17 píxeles aunque alguien ponga en su navegador el tamaño de letra en "grande" o "muy grande". Ese ajuste solo cambia el valor de referencia de rem, y un valor en píxeles nunca lo consulta.
No es un caso raro. Es el ajuste que la gente usa antes de descubrir el zoom, y muchos lo dejan puesto para siempre. En un sitio que calcula todo en píxeles no tiene ningún efecto.
El cambio es pequeño: en html no va ningún tamaño de letra, para que se mantenga el valor del navegador, y todo lo demás se divide entre 16. De 17 px sale 1.0625rem.
clamp() en una línea
font-size: clamp(2.75rem, 2.3333rem + 1.8519vw, 4rem);
Tres valores: suelo, parte fluida, techo. El navegador toma el valor del medio y no lo deja bajar del primero ni subir del tercero.
La parte del medio es la ecuación de una recta, y se puede calcular en vez de probar. Si quieres que la letra mida min a 360 píxeles de ancho de ventana y max a 1440:
pendiente = (max - min) / (1440 - 360)
parte vw = pendiente * 100
parte rem = (min - pendiente * 360) / 16
Para 44 a 64 píxeles sale la línea de arriba. Hay calculadoras en la red que lo hacen por ti, pero se escriben antes tres líneas que se abre una página.
La parte fluida siempre necesita un componente en rem. Un término intermedio en vw puro se desploma hasta el suelo al hacer zoom, y entonces vuelves a tener los saltos, solo que en otro sitio.
Una escala en vez de una lista
Con eso la técnica está resuelta. El problema de verdad era el orden.
Nuestras 183 declaraciones se reducían a 36 valores distintos, y muchos estaban separados por medio píxel: 17,5 y 17 y 16,5. Ninguna persona decidió jamás que esos tres son tres cosas distintas. Se fueron acumulando.
De ahí salieron once escalones, una progresión geométrica con razón 1,13. Cada escalón es 1,13 veces el inmediatamente menor, tanto en el móvil como en el ordenador. Ese es el punto: si todos los escalones crecen con la misma curva, la proporción entre dos títulos se mantiene a cualquier ancho, y la jerarquía aguanta del móvil al ordenador.
El efecto secundario fue la verdadera sorpresa: ningún título se movió más de 1,5 píxeles en el ordenador. Los valores ya estaban cerca de una progresión limpia, simplemente nunca se habían pensado como tal. Todo lo que cambió está por debajo del ancho de ordenador.
La misma tabla de antes, ahora después:
| Elemento | Ordenador | Tableta | Móvil |
|---|---|---|---|
| Título de entrada | 64 px | 54 px | 44,3 px |
| Título de sección | 44,5 px | 38,5 px | 32,7 px |
| Título dentro de una tarjeta | 31 px | 27,7 px | 24,6 px |
| Línea sobre el título de sección | 17 px | 16 px | 15 px |
La proporción entre título de sección y etiqueta es ahora de 2,6 en el ordenador y de 2,2 en el móvil, en vez de 1,8. Y la tarjeta vuelve a quedar un escalón por debajo del título de sección, a cualquier ancho.
Lo que no debe crecer
Algo que falta en muchas guías: el texto corrido no va en la parte fluida.
Es tentador pasarlo todo por la misma fórmula. El resultado, sin embargo, es que el texto se hace más pequeño en el móvil, justo donde hay menos espacio y peor se lee. Por eso nuestros tamaños de lectura son fijos, solo que en rem en vez de px: un párrafo mide lo mismo en el móvil que en el ordenador.
Fluidos, en nuestro caso, son solo los títulos, la entradilla que va debajo y la etiqueta que va encima. Todo lo demás tiene un valor.
Y un segundo suelo que antes no teníamos: en las tarjetas de la portada la letra estaba en cqw, es decir, relativa al ancho de la propia tarjeta. Es la unidad correcta para eso, pero no tiene límite ni por abajo ni por arriba. Por eso una de las etiquetas acababa en 10,5 píxeles a ventana completa. Las unidades de contenedor son estupendas, pero igual que vw necesitan un clamp() alrededor.
De paso: el gris no es un color para versalitas
Durante las mediciones apareció otra cosa que tiene que ver con el tamaño. La línea bajo el título de una entrada, "06.08.2026 · 12 min de lectura · por Ronny Arndt", estaba en un gris con 5,5 : 1 de contraste. Eso cumple la norma, que pide 4,5 : 1.
Aun así apenas se leía, y el motivo es la combinación: 12,5 píxeles, mayúsculas, mucho espaciado. Las mayúsculas se componen casi solo de verticales finas, y con un cuerpo pequeño y trazos ligeros queda demasiado poco color sobre la superficie. Una cifra de contraste mide dos superficies de color entre sí y calla sobre cuánta superficie cubre realmente la letra.
Tres cambios, cada uno pequeño por separado:
- gris de 5,5 : 1 a 8,5 : 1
- todos los tamaños mínimos del sitio a un valor en vez de 12,5 / 13 / 13,5
- mayúsculas pequeñas en seminegrita en lugar de fina
La norma es un suelo. Quien llega a 4,5 : 1 y da el asunto por cerrado construye sitios que no funcionan en una pantalla brillante a plena luz.
Cómo comprobarlo tú mismo
Sin medir, todo esto es cuestión de gusto. Tres caminos que no cuestan nada:
- Poner las herramientas de desarrollo a distintos anchos y leer el tamaño de letra calculado en vez del de la hoja de estilos. Lo interesante son los anchos que quedan entre los dispositivos: 900, 1024, 1180. Ahí están los errores.
- Poner el tamaño de letra del navegador en "muy grande". Si no cambia nada, el sitio está en píxeles.
- Ampliar al 200 por ciento y comprobar si los títulos acompañan. Si se quedan quietos, hay
vwpuro en alguna parte.
En nuestro caso, el segundo y el tercero no daban nada antes de la reforma. Esa es la parte incómoda: no se ve mientras no lo busques.
Si quieres saber cómo se comporta tu sitio entre anchos de pantalla, escríbenos. Medimos los títulos a seis anchos y te mandamos la tabla.
Fuentes
Vigencia de este artículo
Revisado en el lenguaje. Los valores medidos del artículo siguen vigentes.
Preguntas frecuentes sobre tamaños de letra responsivos
¿Están prohibidos los píxeles para el tamaño de letra?
No, y es un malentendido habitual. Los píxeles son correctos en muchos sitios: grosores de borde, espaciado dentro de un control, todo lo que no deba crecer con el texto. Son incorrectos allí donde hay letra. Un valor en px no sigue el ajuste de tamaño de fuente del navegador. Quien lo pone en "muy grande" porque de otro modo lee mal no verá crecer ni una letra en un sitio hecho solo de píxeles.
¿Cuál es la diferencia entre rem y em?
`rem` se refiere siempre al tamaño base del documento, `em` al tamaño de letra del elemento en el que está el valor. Por eso `em` se hereda y se multiplica: una lista con `font-size: 0.9em` dentro de otra lista con `font-size: 0.9em` acaba en 0,81. Para tamaños de letra, `rem` es la opción más tranquila. Para espaciados que deban acompañar a la letra de su propio elemento, `em` sigue siendo lo correcto.
¿Por qué no poner font-size en vw y ya está?
Porque entonces el texto deja de poder ampliarse. Quien amplía una página al 200 por ciento reduce a la mitad el ancho de la ventana en píxeles CSS. Un valor en vw puro se encoge exactamente lo mismo que el zoom debía agrandarlo, y el texto acaba igual que antes. Eso incumple el criterio 1.4.4 de las WCAG. Dentro de clamp(), en cambio, vw es inofensivo, porque el suelo y el techo están en rem y sí acompañan al zoom.
¿Cuántos tamaños de letra necesita un sitio web?
Menos de los que aparecen solos. Nuestro sitio tenía 183 declaraciones con 36 valores distintos, muchos separados por medio píxel. De ahí salieron once escalones para títulos y ocho tamaños de lectura. El principio: quien añade un título elige un escalón que ya existe. Un valor intermedio siempre es señal de que la jerarquía no está pensada.
¿Entre qué anchos debe crecer la letra?
Nosotros calculamos de 360 a 1440 píxeles de ancho de ventana. Por debajo actúa el suelo, por encima el techo. 360 es el ancho por debajo del cual prácticamente ya no queda ningún dispositivo, y 1440 aquel a partir del cual un título no debe seguir creciendo, porque se sale de la columna de lectura. Lo más importante es el techo: sin él, la letra se vuelve absurda en una pantalla de 34 pulgadas.