Tienes un titular a 2 rem en móvil y a 4 rem en escritorio, y por el
camino tres @media para que no se vea ridículo en la tablet. Cada vez que
cambias el diseño hay que tocar los cuatro sitios. clamp() hace eso mismo en
una línea, y además sin saltos: el tamaño acompaña a la ventana de forma continua.
El problema: la escalera de breakpoints
.titulo { font-size: 2rem; }
@media (min-width: 576px) { .titulo { font-size: 2.5rem; } }
@media (min-width: 768px) { .titulo { font-size: 3rem; } }
@media (min-width: 1200px) { .titulo { font-size: 4rem; } }
Funciona, pero el texto va a saltos: a 767 px es pequeño y a 768 px pega un brinco. Y son cuatro lugares que mantener cada vez que el diseñador mueve una medida.
Qué hace exactamente clamp()
.titulo { font-size: clamp(2rem, 1.5rem + 3vw, 4rem); }
Tres valores: mínimo, preferido y máximo. El navegador calcula el preferido y lo recorta si se sale de los límites. Es decir, lo mismo que:
font-size: max(2rem, min(1.5rem + 3vw, 4rem));
El valor del medio es el único que se mueve, porque lleva una unidad relativa a la ventana. Visto en una línea de tiempo:
ventana estrecha ventana media ventana ancha
2rem (mínimo) → 1.5rem + 3vw (crece) → 4rem (máximo)
───────────── ╱ ─────────────
plano crecimiento lineal plano otra vez
La fórmula para no elegir los números a ojo
La parte que casi nadie cuenta: el valor preferido no se inventa, se calcula. Tú decides dos puntos —qué tamaño quieres en la ventana más estrecha y en la más ancha— y sale solo.
Supongamos: 16 px a partir de 320 px de ventana, y 24 px al llegar a 1280 px.
pendiente = (24 - 16) / (1280 - 320) = 8 / 960 = 0.00833
en vw = 0.00833 × 100 = 0.833vw
base = 16 - (0.00833 × 320) = 13.33px = 0.833rem
font-size: clamp(1rem, 0.833rem + 0.833vw, 1.5rem);
Ese 0.833rem es lo que hace que a 320 px de ventana el resultado sea exactamente
1 rem, y a 1280 px exactamente 1.5 rem. Entre medias, una recta.
Si no te apetece hacer cuentas, hay generadores que dan la expresión a partir de esos cuatro números; pero conviene entender la fórmula para saber qué estás pegando.
No es solo para texto
Cualquier propiedad que acepte una longitud acepta clamp(). Los espaciados son
un caso tan bueno como la tipografía, porque un padding fijo de 4 rem asfixia
en móvil y se queda corto en un monitor grande:
.seccion {
padding-block: clamp(2rem, 5vw, 6rem);
gap: clamp(1rem, 2vw, 2.5rem);
}
.contenedor {
inline-size: clamp(20rem, 90%, 70rem); /* ancho fluido con topes */
margin-inline: auto;
}
Ese inline-size es un buen ejemplo del patrón completo: nunca menos de 20 rem,
nunca más de 70 rem y, entre medias, el 90 % de lo que haya. Sustituye al típico
width: 90%; max-width: 70rem; y además pone un suelo.
Una escala tipográfica entera
Definiendo los pasos como variables tienes un sistema completo que escala solo:
:root {
--paso--1: clamp(0.83rem, 0.78rem + 0.22vw, 0.94rem);
--paso-0: clamp(1rem, 0.93rem + 0.35vw, 1.19rem);
--paso-1: clamp(1.2rem, 1.09rem + 0.53vw, 1.5rem);
--paso-2: clamp(1.44rem, 1.28rem + 0.8vw, 1.89rem);
--paso-3: clamp(1.73rem, 1.49rem + 1.19vw, 2.38rem);
}
h1 { font-size: var(--paso-3); }
h2 { font-size: var(--paso-2); }
p { font-size: var(--paso-0); }
Cambias los extremos en un sitio y se recalcula toda la página. Eso es lo que convierte a
clamp() en algo más que un truco suelto.
Aquí mismo, en este blog
El titular que has leído arriba está escrito así:
.article-title {
font-size: clamp(2.25rem, 1.5rem + 3vw, 4rem);
line-height: 1.05;
}
.article-content h2 {
font-size: clamp(1.5rem, 1.2rem + 1vw, 2rem);
}
Sin un solo @media para la tipografía. Si estrechas la ventana ahora mismo,
verás el título encogerse de forma continua hasta plantarse en 2.25 rem.
Lo que se rompe si no lo sabes
- Un valor preferido solo con
vwes un problema de accesibilidad.clamp(1rem, 4vw, 2rem)ignora el zoom de texto del navegador: quien necesita ampliar la letra no puede. Incluye siempre una parte enrem(0.833rem + 0.833vw), que es lo que mantiene la proporcionalidad con el ajuste del usuario. vwmira la ventana, no el contenedor. El mismo componente dentro de una barra lateral estrecha seguirá calculando el tamaño con el ancho total de la pantalla. Para eso están las container queries y la unidadcqi.- Si el mínimo es mayor que el máximo, gana el mínimo. No da error ni aviso: simplemente se queda clavado y te vuelves loco buscando por qué no escala.
- El
line-heightno escala solo. Ponlo sin unidades (1.05,1.7) para que siga al tamaño de fuente, y recuerda que un titular grande pide interlineado más apretado que uno pequeño. - Comprueba los extremos de verdad. Al no haber breakpoints es fácil no mirar nunca a 320 px ni a 2560 px, que son justo donde tus dos topes entran en juego.
- No todo tiene que ser fluido. Los grosores de borde, los iconos de interfaz o las alturas de un botón suelen quedar mejor fijos: si todo se mueve, nada parece estable.
La chuleta
| Quiero… | Escribo |
|---|---|
| Texto fluido con topes | clamp(1rem, 0.83rem + 0.83vw, 1.5rem) |
| Espaciado que escala | padding-block: clamp(2rem, 5vw, 6rem) |
| Ancho con suelo y techo | inline-size: clamp(20rem, 90%, 70rem) |
| Solo un tope superior | min(90%, 70rem) |
| Solo un tope inferior | max(2rem, 5vw) |
Y ya está
Mínimo, preferido y máximo. Con la fórmula de los dos puntos eliges los números con criterio
en lugar de a ojo, y con una parte en rem en el valor preferido no te cargas la
accesibilidad. A cambio, borras la mitad de tus media queries y el diseño deja de dar
brincos entre tamaños de pantalla.