O que o clamp() faz
clamp(MIN, PREFERRED, MAX) recebe três valores e devolve o do meio, desde que ele fique entre os outros dois. O uso clássico é um título que cresce com a tela, mas para em limites razoáveis, sem media query:
O valor preferido é 1rem + 3vw: 16px mais 3% da largura. Em uma prévia com 800px de largura, isso dá 16 + 24 = 40px, que está entre 24px (1.5rem) e 48px (3rem), então o título fica com 40px. Em um celular de 320px, o valor preferido é 25.6px. Acima de 1067px ele passaria de 48px, então para em 48px. Redimensione a janela para ver o número mudar; aqui o vw é uma porcentagem da largura do frame da prévia.
Veja sem redimensionar a janela
O vw segue a viewport, que é difícil de mudar enquanto você lê. As unidades de container query seguem um contêiner: cqi é 1% da largura do contêiner. Arraste o controle deslizante para mudar a caixa, e o mesmo tipo de clamp() responde:
Deslize até o começo e o título para em 20px (o MIN). Deslize até o fim e ele para em 40px (o MAX). No meio, ele segue 0.5rem + 6cqi. É o mesmo mecanismo da versão com vw, com uma régua menor.
Os três argumentos
font-size: clamp(1rem, 0.8rem + 1vw, 1.5rem);
/* MIN PREFERRED MAX */
| Argumento | Papel | Unidade típica |
|---|---|---|
| MIN | o menor valor permitido | rem |
| PREFERRED | o valor que muda com a tela | rem + vw (ou cqi) |
| MAX | o maior valor permitido | rem |
As contas funcionam dentro de cada argumento sem escrever calc(): 1rem + 2vw está certo do jeito que está. O + e o - precisam de um espaço dos dois lados, senão a declaração inteira é inválida.
Se o MIN for maior que o MAX, o MIN vence: clamp(3rem, 5vw, 2rem) é sempre 3rem.
Calcular o valor do meio
Para uma fonte crescer de 16px em uma tela de 320px até 24px em uma tela de 1280px:
- Inclinação: (24 − 16) ÷ (1280 − 320) = 8 ÷ 960 = 0.00833, que dá 0.833vw (o vw é por 100px).
- Ponto de partida: 16px − 0.00833 × 320px = 13.33px, que dá 0.833rem.
- Coloque os limites em volta:
font-size: clamp(1rem, 0.833rem + 0.833vw, 1.5rem);
Com 320px de largura isso dá 13.33 + 2.67 = 16px, com 1280px dá 13.33 + 10.67 = 24px, e fora dessa faixa fica nos limites. As "calculadoras de clamp" online fazem exatamente essa conta.
min() e max()
clamp() é uma combinação de duas funções mais simples:
min(a, b)devolve o valor menor, então define um limite superior.max(a, b)devolve o valor maior, então define um limite inferior.clamp(MIN, VAL, MAX)é o mesmo quemax(MIN, min(VAL, MAX)).
Os nomes parecem invertidos no começo: para dizer "no máximo 600px", você usa min().
Na prévia larga, o primeiro card para em 420px. Dentro do pai de 260px, 100% é o valor menor, então o segundo card fica com 260px. max(12px, 3%) dá ao primeiro card 3% da largura do pai (o body: uns 23.5px em uma prévia de 800px), e ao segundo 12px, porque 3% de 260px (7.8px) fica abaixo do piso.
width: min(100%, 420px) substitui o par antigo width: 100%; max-width: 420px; em uma única declaração.
Além do tamanho da fonte: espaçamentos e larguras
clamp() funciona em qualquer propriedade que aceite um comprimento. Porcentagens no valor do meio deixam um componente fluido em relação ao pai, e não à viewport:
No pai de 300px, o card tem 240px de largura (80%) com 15px de padding (5% de 300px). No pai de 760px, 80% daria 608px, então o card para no máximo de 520px, e 5% de 760px dá 38px, então o padding para em 32px.
Acessibilidade: mantenha rem no valor do meio
Um tamanho de fonte feito só de vw, como font-size: 5vw, não cresce quando o leitor aumenta o tamanho de fonte padrão nas configurações do navegador, e também não cresce com o zoom, porque dar zoom deixa a viewport mais estreita em pixels CSS. Acrescentar uma parte em rem (1rem + 2vw) e limites em rem mantém o texto ligado à configuração do leitor. A página de unidades explica rem e vw em detalhe.
Erros comuns
- Usar
min()para um mínimo.min()escolhe o valor menor, que é um limite superior. Para "pelo menos 12px", usemax(12px, ...). - Sem espaços em volta de
+ou-.clamp(1rem, 1rem+2vw, 3rem)é inválido, e a propriedade volta ao valor anterior. - Só
vwno meio. O texto passa a ignorar a configuração de fonte do leitor. Acrescente um termo emrem. - MIN maior que MAX. O resultado é sempre o MIN, o que raramente era a intenção.
- Limites em
pxem tamanhos de fonte. Eles travam o texto até para leitores que precisam dele maior. Userem.
Perguntas frequentes
O que o clamp() faz no CSS?
clamp(MIN, PREFERRED, MAX) usa o valor preferido enquanto ele fica entre os dois limites, e o limite mais próximo caso contrário. font-size: clamp(1rem, 4vw, 2rem) segue 4% da largura da viewport, mas nunca fica abaixo de 1rem nem acima de 2rem.
Como fazer um tamanho de fonte responsivo com clamp?
Coloque um valor baseado na viewport no meio e limites fixos nas pontas, e misture rem no meio para o texto continuar seguindo a configuração de fonte do leitor: font-size: clamp(1.5rem, 1rem + 2vw, 3rem);.
O que acontece se o mínimo for maior que o máximo no clamp()?
O mínimo vence. clamp(3rem, 5vw, 2rem) sempre dá 3rem, porque o clamp() aplica o mínimo depois do máximo.
Qual a diferença entre min() e max() no CSS?
min() devolve o menor dos valores, então funciona como limite superior: width: min(100%, 600px) nunca passa de 600px. max() devolve o maior, então funciona como limite inferior: font-size: max(1rem, 2vw) nunca fica menor que 1rem.
O clamp() é suportado em todos os navegadores?
Sim, clamp(), min() e max() funcionam em todas as versões atuais de Chrome, Edge, Firefox e Safari, e podem ser usados em qualquer propriedade que aceite comprimento, número, porcentagem ou ângulo.