Caixa, fluxo, flex e grid
Pule esta página se você já sabe…
- o que
box-sizing: border-boxmuda na conta da largura; - a diferença entre eixo principal e eixo cruzado no flexbox;
- quando grid é a resposta e quando flex é;
- por que uma container query responde melhor que uma media query.
O problema
Você quer duas colunas de 50% lado a lado, com um respiro entre elas:
.coluna {
width: 50%;
padding: 16px;
float: left;
}
E elas quebram para baixo. O motivo é a conta da caixa: por padrão, width:
50% é a largura do conteúdo, e o padding é somado por fora. Cada coluna
ocupa 50% + 32px, e duas não cabem em 100%.
Uma linha resolve, e é a primeira linha de qualquer CSS moderno:
*,
*::before,
*::after {
box-sizing: border-box;
}
Com border-box, width: 50% passa a incluir padding e border. A conta fecha.
O modelo de caixa
Todo elemento é quatro retângulos concêntricos:
┌──────────── margin ────────────┐
│ ┌────────── border ──────────┐ │
│ │ ┌──────── padding ───────┐ │ │
│ │ │ content │ │ │
│ │ └────────────────────────┘ │ │
│ └────────────────────────────┘ │
└────────────────────────────────┘
- content — o texto ou a imagem.
- padding — respiro dentro, pintado com o fundo do elemento.
- border — a linha.
- margin — respiro fora, transparente. Margens verticais adjacentes
colapsam entre si (duas de 16px viram uma de 16px, não 32px) — motivo pelo
qual
gapcostuma ser mais previsível.
Flexbox: uma dimensão
Flex distribui filhos ao longo de um eixo. É a ferramenta para barra, toolbar, linha de botões, lista vertical.
<!doctype html>
<html lang="pt-BR">
<head>
<meta charset="utf-8" />
<title>Flex</title>
<style>
*,
*::before,
*::after {
box-sizing: border-box;
}
.barra {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 12px;
border: 1px solid #ddd;
}
.titulo {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>
</head>
<body>
<div class="barra">
<strong class="titulo">Um título muito comprido que não cabe na barra inteira</strong>
<button type="button">Editar</button>
<button type="button">Excluir</button>
</div>
</body>
</html>
| Propriedade | O que faz |
|---|---|
display: flex |
Liga o eixo principal (horizontal por padrão). |
justify-content |
Distribui no eixo principal. |
align-items |
Alinha no eixo cruzado (vertical, aqui). |
gap |
Espaço entre filhos, sem margens colapsando. |
flex: 1 |
"Cresça para ocupar a sobra." |
min-width: 0 |
O destravamento do truncamento — veja abaixo. |
min-width: 0 é a linha que falta em 90% dos truncamentos quebrados
O tamanho mínimo padrão de um item flex é auto, que é o tamanho do
conteúdo. Um texto longo simplesmente se recusa a encolher, e empurra os
botões para fora da barra. min-width: 0 diz "pode encolher abaixo do
conteúdo", e só aí text-overflow: ellipsis tem efeito.
Grid: duas dimensões
Grid define linhas e colunas de uma vez. É a ferramenta para layout de página, formulário de duas colunas, galeria de cartões.
.galeria {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
gap: 16px;
}
Essa linha sozinha é um layout responsivo inteiro, sem media query: "quantas colunas couberem, cada uma com no mínimo 240px, dividindo a sobra igualmente".
Regra prática de escolha
Uma direção e o conteúdo manda no tamanho → flex. Duas direções e o contêiner manda no tamanho → grid. Barra de botões é flex; a página inteira é grid.
Container query: o breakpoint certo
Uma media query pergunta o tamanho da janela. Quase sempre a pergunta errada: um componente dentro de uma sidebar de 320px, numa janela de 1600px, recebe o layout de desktop e fica espremido.
Container query pergunta o tamanho do contêiner:
.painel {
container-type: inline-size;
container-name: painel;
}
@container painel (min-width: 40rem) {
.cartao {
grid-column: span 6;
}
}
O mesmo componente funciona full-bleed, dentro de uma sidebar ou dentro de uma gaveta — porque a pergunta passou a ser sobre o espaço que ele de fato tem.
Onde isso aparece no SDK
O SDK publica uma folha opt-in de layout, utilities.css, que não vem no
bundle padrão. Importe quando quiser:
import "tempest-react-sdk/styles.css";
import "tempest-react-sdk/utilities.css"; // opcional
Ela traz as receitas acima já nomeadas — .tempest-stack, .tempest-cluster,
.tempest-row, .tempest-grid-auto, .tempest-sidebar-layout,
.tempest-form-grid — e a receita de página inteira, o dashboard:
<div class="tempest-dashboard">
<section class="tempest-widget tempest-widget-half">Vendas</section>
<section class="tempest-widget tempest-widget-half">Visitas</section>
<section class="tempest-widget tempest-widget-tall">Série temporal</section>
</div>
.tempest-dashboard é um grid de 12 colunas com container-type: inline-size, e os
spans dos widgets abrem em duas etapas — 40rem e 64rem — do contêiner, não da
janela. Um widget nasce ocupando a largura toda, porque dashboard lido no celular é
uma coluna só, e essa é a maior parte da vida dele.
Detalhes e a lista completa em Estilos & Design Tokens.
Recap
box-sizing: border-boxfazwidthincluirpaddingeborder— é a primeira linha do seu CSS. ✅- Margens verticais adjacentes colapsam;
gapnão colapsa, por isso é mais previsível. - Flex é uma dimensão (barra, toolbar); grid é duas (página, galeria, formulário).
min-width: 0é o que deixa um item flex encolher abaixo do conteúdo — sem eleellipsisnão funciona.- Container query pergunta o tamanho do contêiner, que é a pergunta certa para um componente reusável.
- No SDK,
utilities.cssé opt-in e traz essas receitas nomeadas, incluindo o.tempest-dashboardcom spans por container query.
📚 Referência canônica: MDN — Flexbox · MDN — Grid
➡️ Próxima página: Custom properties e tema