Arraste um controle de largura da viewport e veja calc(), min(), max() e clamp() se resolverem em pixels. Mais vh vs svh, lvh e dvh, fit-content e min-content ao vivo, gap e receitas de tipografia fluida.
As funções matemáticas do CSS deixam um único valor se adaptar à tela. calc() mistura unidades, como em calc(100% - 2rem). min() escolhe a menor opção, então width: min(100%, 640px) nunca transborda. max() escolhe a maior, e clamp(min, preferred, max) mantém um valor fluido entre dois limites. dvh acompanha a barra de ferramentas variável do navegador no celular, ao contrário do vh simples.
Qual função para cada tarefa
Tarefa
CSS
Largura total menos uma margem fixa
width: calc(100% - 2rem)
Uma coluna limitada a 640px
width: min(100%, 640px)
Padding que nunca fica abaixo de 1rem
padding: max(1rem, 4vw)
Título que escala entre 2rem e 3.5rem
font-size: clamp(2rem, 1.2rem + 3vw, 3.5rem)
Hero que preenche a tela visível do celular
min-height: 100dvh
Em vez de redimensionar o navegador para testar uma fórmula, arraste a largura simulada da viewport e cada função se resolve em pixels na sua frente, com o ponto em que clamp() atinge os limites marcado. A página também desenha o que vh, svh, lvh e dvh medem em um celular e mostra as palavras-chave intrínsecas funcionando em caixas reais.
Arraste o controle de largura da viewport do tamanho de um celular até um monitor largo.
Ajuste os valores mínimo, preferido e máximo da fórmula clamp() e acompanhe o resultado em pixels.
Compare as linhas de min(), max() e calc() resolvidas na mesma largura.
Copie a fórmula e depois experimente as caixas de dimensionamento por conteúdo e os exemplos de gap abaixo.
Os espaços em volta de + e - dentro de calc() são obrigatórios. calc(100%-2rem) é inválido; calc(100% - 2rem) funciona.
Mantenha um termo em rem no meio de um clamp() de fonte fluida, para que o texto ainda responda quando o leitor der zoom ou mudar o tamanho padrão.
min() e max() parecem invertidos no começo: min() define um tamanho máximo, porque sempre pega o menor valor.
Use dvh em seções de tela cheia com moderação, já que o valor muda conforme a barra de ferramentas se move e pode deslocar o conteúdo durante a rolagem. svh é a escolha estável.
Perguntas frequentes
Qual é a diferença entre vh, svh, lvh e dvh?
Nos celulares, a barra de ferramentas do navegador cresce e encolhe. svh é 1% da viewport pequena, com a barra visível. lvh é 1% da viewport grande, com a barra oculta. dvh acompanha a que estiver valendo no momento e se atualiza durante a rolagem. O vh clássico geralmente equivale a lvh, e é por isso que seções com 100vh ficam cortadas no celular.
clamp(), min() e max() funcionam em todos os navegadores?
Sim, as três funcionam em todos os principais navegadores desde 2020. As unidades de viewport pequena, grande e dinâmica chegaram depois, ao longo de 2022, e hoje estão em todos os principais navegadores atuais. Adicione uma linha de fallback com vh simples antes delas se você ainda dá suporte a dispositivos antigos.
Como escrevo um tamanho de fonte fluido com clamp()?
Escolha o tamanho em uma tela estreita e em uma tela larga e escreva clamp(pequeno, preferido, grande). O valor preferido combina rem e vw, como 1rem + 2vw, então o tamanho cresce com a janela mas fica entre os dois limites. O laboratório abaixo mostra as larguras exatas em que os limites assumem.
O que fit-content faz?
width: fit-content dimensiona uma caixa pelo conteúdo, como um inline-block ajustado, mas nunca mais larga que o espaço disponível. Equivale a min(max-content, max(min-content, espaço disponível)). A função fit-content() em trilhas de grid faz o mesmo com um limite que você escolhe.
Dá para usar gap com flexbox?
Sim. gap, row-gap e column-gap funcionam em contêineres flex em todos os navegadores atuais, não só no grid. O gap é adicionado apenas entre os itens, nunca nas bordas externas, o que é mais simples do que margens em cada filho.
Como calc() é resolvido
calc() espera até o momento do layout para ser resolvido, então pode combinar uma porcentagem que depende do pai com um valor em rem ou pixels. Você pode aninhar calc() dentro de min(), max() e clamp() e usar custom properties dentro dele, como calc(var(--gutter) * 2).
Multiplicação e divisão precisam de pelo menos um número puro: calc(2 * 1rem) funciona, calc(1rem * 1rem) não. Divisão por zero torna a declaração inválida.
Tamanhos intrínsecos: min-content, max-content e fit-content
min-content é a menor largura que uma caixa pode ter sem transbordar, geralmente a largura da sua palavra mais longa ou da imagem mais larga. max-content é a largura que ela teria se o texto nunca quebrasse. Os dois são úteis para trilhas de grid e para rótulos que devem abraçar o texto.
fit-content fica entre os dois: é tão larga quanto o conteúdo pede, mas quebra quando o contêiner é mais estreito. Isso a torna uma forma limpa de centralizar uma caixa ajustada com margin-inline: auto.
Espaçamento fluido, além de tipografia fluida
O mesmo truque de clamp() funciona para padding, margens e gaps. Uma seção com padding-block: clamp(2rem, 6vw, 6rem) respira em telas grandes sem desperdiçar espaço no celular.
Defina os valores fluidos uma vez como custom properties, por exemplo --space-m e --step-2, e use-os em todo lugar. Mudar a escala depois significa editar uma linha em vez de caçar nos componentes.
vh vs svh, lvh e dvh
Unidades de porcentagem da viewport
Unidade
1 unidade equivale a
Muda durante a rolagem?
Use para
vh / vw
1% da viewport (no celular, geralmente a grande)
Não
Layouts de desktop, fallback para navegadores antigos
svh / svw
1% da viewport pequena, barras visíveis
Não
Seções de tela cheia que nunca podem ficar escondidas
lvh / lvw
1% da viewport grande, barras ocultas
Não
Fundos que devem cobrir tudo
dvh / dvw
1% da viewport atual
Sim
Layouts que devem acompanhar a barra de ferramentas
vmin / vmax
1% do lado menor ou maior
Não
Elementos quadrados que cabem em qualquer orientação
cqi / cqw
1% do tamanho inline de um contêiner de tamanho
Junto com o contêiner
Componentes dentro de container queries
Um hero de altura total seguro no celular
A primeira linha é o fallback para navegadores sem as unidades novas. A segunda a sobrescreve onde há suporte.
Exemplos de calc(), min(), max() e clamp()
Uma coluna legível sem media query
min() limita a largura; o padding usa max() para nunca encolher abaixo de 12px. As duas regras se adaptam sozinhas à largura do quadro.
calc() para uma barra lateral fixa ao lado de uma área principal fluida
A área principal ocupa o que sobra depois da barra lateral de 120px e do gap de 12px.
min-content, max-content e fit-content
Palavras-chave de dimensionamento intrínseco
Palavra-chave
A largura vira
Tailwind
A palavra mais longa sem quebra ou a imagem mais larga
Todo o conteúdo em uma linha, mesmo que transborde
max-content, mas não mais largo que o espaço disponível
fit-content(300px) em grid
Como fit-content com um teto de 300px
grid-cols-[fit-content(300px)_1fr]
gap em flex e grid
O mesmo gap em uma linha flex com quebra e em um grid
row-gap e column-gap podem ser diferentes. Nenhum dos dois adiciona espaço nas bordas externas.
Escala fluida de tipografia e espaçamento
Uma pequena escala fluida como custom properties
Cada degrau cresce entre um celular de cerca de 360px e um desktop de 1280px. Ajuste os números no laboratório acima.
Laboratório de viewport
Largura simulada da viewport (px)
Título fluido em {px}px
Valores resolvidos na largura simulada
Função
Declaração
Em {vp}px
mínimo do clamp (rem)
máximo do clamp (rem)
preferido: parte em rem
preferido: parte em vw
O máximo está abaixo do mínimo, então o mínimo vence em qualquer largura.
Fica em {min}rem até cerca de {from}px de largura, cresce até cerca de {to}px e depois se mantém em {max}rem.
Sem parte em vw, o valor nunca muda com a janela.
Copiar
O que 100 de cada unidade cobre em um celular
Três celulares: 100svh preenche o espaço entre as barras de ferramentas visíveis, 100lvh preenche a tela toda como se as barras estivessem ocultas, 100dvh acompanha as barras conforme elas mudam
barras visíveis
barras ocultas
acompanha as barras
As faixas cinza são as barras de ferramentas do navegador. O azul é a área que 100 unidades preenchem.
Dimensionamento por conteúdo, ao vivo
Palavra-chave de largura
Espaço disponível (px)
Frete grátis em todos os pedidos neste fim de semana