Flexbox CSS: alinhe e distribua elementos com clareza
Aprenda container, itens, eixos, gap, flex e wrap criando uma prateleira de livros, com posições e transbordamento medidos no navegador.
Flexbox organiza os filhos diretos de um contêiner em uma linha ou coluna e
distribui o espaço disponível entre eles. Com display: flex, você consegue
alinhar cartões, criar menus e permitir que itens cresçam, encolham ou quebrem
de linha sem calcular a posição de cada um na mão.
Nesta lição, três livros vão ocupar uma prateleira de 600 pixels. As posições, os tamanhos e o transbordamento foram medidos no Google Chrome 151.0.7922.170. Antes de distribuir caixas, vale entender como o box model calcula a largura real, porque padding e border também consomem o espaço que o Flexbox precisa repartir.
A prateleira define a direção; os livros ocupam o espaço
Imagine uma prateleira com três livros. A prateleira é o flex container; os livros colocados diretamente nela são os flex items. O comprimento da prateleira representa o main axis, ou eixo principal. A direção da altura é o cross axis, ou eixo transversal. O trecho que sobra depois de acomodar os livros é o espaço livre que o Flexbox pode distribuir.
O mapeamento volta ao CSS assim: display: flex cria o container,
flex-direction escolhe a direção do eixo principal, justify-content trabalha
nesse eixo e align-items trabalha no eixo transversal. A analogia tem limite:
itens flex podem crescer e encolher, e o eixo pode virar uma coluna. Além disso,
quando existe flex-wrap, cada linha distribui seu próprio espaço; não é uma
prateleira física contínua.
Comece com uma estrutura sem elementos extras entre o container e os itens:
<div class="prateleira" id="prateleira">
<article class="livro">Livro 1</article>
<article class="livro">Livro 2</article>
<article class="livro">Livro 3</article>
</div>Os três article são filhos diretos e, portanto, viram flex items. Um título
dentro de um article não vira item do container externo; ele participa do
layout interno do próprio cartão. Essa distinção evita aplicar flex no lugar
errado.
O primeiro display flex e seus padrões
Ative Flexbox no pai. Sem outras propriedades, o eixo principal usa row, os
itens começam em flex-start, podem encolher e não quebram para outra linha.
.prateleira {
display: flex;
width: 600px;
}
.livro {
border: 2px solid currentColor;
}Quando você muda flex-direction para column, o eixo principal deixa de
percorrer a linha e passa a percorrer a coluna:
.prateleira {
display: flex;
flex-direction: column;
}Por isso, memorize os termos principal e transversal, não “horizontal”
e “vertical”. Com row, justify-content costuma mover no sentido horizontal;
com column, a mesma propriedade trabalha no sentido vertical.
Também existem row-reverse e column-reverse. Eles mudam a apresentação, mas
não alteram a ordem dos elementos no HTML. Leitores de tela e navegação por Tab
continuam seguindo a ordem do documento. Use reversão para uma necessidade
visual, não para consertar uma estrutura semântica fora de ordem.
Distribuir exige saber quanto espaço sobrou
Agora vamos fixar uma medida previsível para cada livro. O shorthand
flex: 0 0 100px reúne flex-grow, flex-shrink e flex-basis: não crescer,
não encolher e começar com 100 pixels.
.prateleira {
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
width: 600px;
height: 140px;
padding: 20px;
}
.prateleira > .livro {
box-sizing: border-box;
flex: 0 0 100px;
height: 60px;
}A largura interna disponível é 560: os 600 pixels incluem 20 de padding em
cada lado. Os três livros consomem 300, então sobram 260. Com
space-between, esse espaço é repartido nos dois intervalos: 130 pixels em
cada um.
O teste leu a posição de cada livro em relação à borda esquerda e superior do container:
const prateleira = document.querySelector('#prateleira');
const base = prateleira.getBoundingClientRect();
const posicoes = [...prateleira.children].map((livro) => {
const caixa = livro.getBoundingClientRect();
return {
x: caixa.x - base.x,
y: caixa.y - base.y,
width: caixa.width,
height: caixa.height,
};
});
console.table(posicoes);Os x confirmam os intervalos: o primeiro começa depois dos 20 pixels de
padding; o segundo começa em 20 + 100 + 130 = 250; o terceiro, em 480. O
y: 40 também tem explicação: sobram 80 pixels na altura interna, e
align-items: center deixa 40 acima do livro.
Se justify-content parece não fazer nada, pergunte primeiro: existe espaço
livre no eixo principal? Um item com width: 100% pode consumir tudo e não
deixar nada para distribuir. E não tente trocar por justify-items: essa
propriedade é ignorada no layout Flexbox.
Gap é a distância; justify-content distribui a sobra
gap cria uma distância estável entre itens. justify-content distribui o
espaço que sobrou depois de considerar tamanhos e gaps. São responsabilidades
diferentes.
.lista-produtos {
display: flex;
gap: 16px;
justify-content: flex-start;
}Use gap quando o requisito diz “mantenha 16 pixels entre os cartões”. Use
space-between quando diz “encoste o primeiro e o último nas pontas e reparta
a sobra entre eles”. Num menu, essa diferença aparece quando a largura da tela
muda: o gap permanece; a sobra é recalculada.
O margin ainda funciona em flex items, inclusive margin-inline-start: auto
para consumir o espaço livre antes de um item. Mas, quando a distância pertence
ao conjunto inteiro, gap deixa essa intenção visível no container e evita
margens especiais no primeiro ou no último cartão.
Crescer, encolher e usar uma base
O shorthand flex responde como o item participa quando há sobra ou falta de
espaço:
.produto-card {
flex: 1 1 14rem;
min-width: 0;
}O primeiro 1 é flex-grow: o item pode receber uma parte da sobra. O segundo
é flex-shrink: ele pode encolher quando faltar espaço. 14rem é
flex-basis, o tamanho inicial usado na negociação. Se três cartões usam a
mesma configuração, eles dividem a sobra com a mesma proporção.
min-width: 0 merece atenção em cards com textos longos. Flex items têm um
tamanho mínimo automático baseado no conteúdo; uma URL ou palavra sem quebra
pode impedir o encolhimento. Zerar o mínimo permite que as regras de quebra do
conteúdo façam seu trabalho. Isso não significa colocar min-width: 0 em tudo,
mas reconhecer o padrão quando um item isolado insiste em transbordar.
Wrap cria novas linhas de itens inteiros
Uma coleção de 320 pixels recebe três livros de 140 e um gap de 16. Dois cabem
na primeira linha, porque 140 + 16 + 140 = 296; o terceiro precisa ir para a
linha seguinte.
.colecao {
display: flex;
flex-wrap: wrap;
width: 320px;
gap: 16px;
}
.colecao > .livro {
box-sizing: border-box;
flex: 0 0 140px;
height: 60px;
}O navegador confirmou as coordenadas relativas dos três itens:
const colecao = document.querySelector('.colecao');
const origem = colecao.getBoundingClientRect();
const posicoes = [...colecao.children].map((item) => {
const caixa = item.getBoundingClientRect();
return { x: caixa.x - origem.x, y: caixa.y - origem.y };
});
console.table(posicoes);O segundo começa em 156 porque há 140 pixels de item e 16 de gap. O terceiro
volta ao começo em x: 0 e desce para y: 76: 60 de altura mais 16 de gap.
Flexbox resolveu uma dimensão por linha; ele não criou colunas compartilhadas
entre todas as linhas. Se o alinhamento em duas dimensões for requisito, CSS
Grid tende a representar melhor o problema.
O erro: pedir três livros onde só cabem dois
Retire o flex-wrap ou deixe o valor inicial nowrap, mantendo os itens sem
permissão para encolher:
.colecao-sem-quebra {
display: flex;
flex-wrap: nowrap;
width: 320px;
gap: 16px;
}
.colecao-sem-quebra > .livro {
flex: 0 0 140px;
}A conta pede 452 pixels: três vezes 140, mais dois gaps de 16. Como o container oferece 320, os itens avançam 132 pixels além dele. Esta medição reproduz o defeito:
const lista = document.querySelector('.colecao-sem-quebra');
console.log('largura disponível:', lista.clientWidth);
console.log('largura necessária:', lista.scrollWidth);
console.log('excesso:', lista.scrollWidth - lista.clientWidth);A correção depende do requisito. Se os cartões devem manter 140 pixels, permita a quebra:
.colecao-sem-quebra {
flex-wrap: wrap;
}Se devem permanecer na mesma linha, permita encolhimento ou escolha uma base
menor. Se a fileira representa uma galeria horizontal intencional, mantenha
nowrap e use overflow-x: auto com controles acessíveis. Não existe uma
propriedade universal; existe uma decisão de produto expressa no CSS.
Sua missão: transformar uma lista em menu responsivo
Crie um menu que começa empilhado em telas estreitas e vira linha a partir de 640 pixels. O HTML deve continuar na ordem lógica de leitura:
<nav aria-label="Categorias da livraria">
<ul class="menu">
<li><a href="#romance">Romance</a></li>
<li><a href="#tecnologia">Tecnologia</a></li>
<li><a href="#biografias">Biografias</a></li>
</ul>
</nav>.menu {
display: flex;
flex-direction: column;
gap: 12px;
padding: 0;
list-style: none;
}
@media (min-width: 640px) {
.menu {
flex-direction: row;
align-items: center;
}
}O critério de sucesso é verificável: a 639 pixels, os três itens devem ter
coordenadas y diferentes; a 640 pixels, devem compartilhar o mesmo y. Navegue
também com Tab e confirme que a sequência continua Romance, Tecnologia e
Biografias — nenhuma propriedade visual deve inverter a ordem semântica.
Se uma declaração de Flexbox não chega ao container, revise seletores e cascata. Se ela chega, mas aparece riscada, investigue a especificidade da regra. Em projetos React, o mesmo mecanismo continua valendo; o que muda é como a folha entra no componente, assunto de CSS no React.
Perguntas frequentes
Flexbox serve para linha e para coluna?
Qual é a diferença entre justify-content e align-items?
Quando devo usar Flexbox e quando devo usar Grid?
Por que flex-wrap não quebra palavras compridas?
Dúvidas e comentários
Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.
Entrar para perguntarÉ o mesmo login gratuito dos cursos.
Nenhuma dúvida por aqui ainda — a primeira pode ser a sua.
Todo o código deste artigo foi executado em Google Chrome 151.0.7922.170, e as saídas exibidas são as reais — como produzimos este conteúdo.
Fontes consultadas
- MDN — Basic concepts of flexbox — developer.mozilla.org
- MDN — Aligning items in a flex container — developer.mozilla.org
- MDN — flex — developer.mozilla.org
- CSS Flexible Box Layout Module Level 1 — W3C — w3.org


