Menu

clamp() no CSS: fonte fluida, min() e max()

clamp(MIN, PREFERIDO, MAX) devolve o valor preferido, mas nunca menos que MIN nem mais que MAX. Veja como ele deixa tamanhos de fonte e espaçamentos fluidos sem media queries, como calcular o valor do meio e qual a relação dele com min() e max().

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

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    */
ArgumentoPapelUnidade típica
MINo menor valor permitidorem
PREFERREDo valor que muda com a telarem + vw (ou cqi)
MAXo maior valor permitidorem

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:

  1. Inclinação: (24 − 16) ÷ (1280 − 320) = 8 ÷ 960 = 0.00833, que dá 0.833vw (o vw é por 100px).
  2. Ponto de partida: 16px − 0.00833 × 320px = 13.33px, que dá 0.833rem.
  3. 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 que max(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", use max(12px, ...).
  • Sem espaços em volta de + ou -. clamp(1rem, 1rem+2vw, 3rem) é inválido, e a propriedade volta ao valor anterior.
  • Só vw no meio. O texto passa a ignorar a configuração de fonte do leitor. Acrescente um termo em rem.
  • MIN maior que MAX. O resultado é sempre o MIN, o que raramente era a intenção.
  • Limites em px em tamanhos de fonte. Eles travam o texto até para leitores que precisam dele maior. Use rem.

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.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR