Todos os artigos
82 artigos · atualizado semanalmente Veja nossas Ferramentas
Todos os artigos
Todos

CSS Grid vs Flexbox: quando usar cada um

Grid é bidimensional, Flexbox é unidimensional. A escolha certa entre os dois depende do que o layout está tentando fazer — não de preferência pessoal.

COVER · Todos

Todo projeto começa igual: alguém usa Flexbox pra tudo. Funciona até aparecer aquele layout com coluna lateral fixa, header e conteúdo principal que precisa se ajustar em altura — aí vira uma série de hacks com flex-wrap, align-self e min-height que ninguém consegue mais manter. A pergunta que deveria ter sido feita antes: esse layout é uma linha ou uma grade?

A resposta para isso é o divisor entre Flexbox e CSS Grid.


A regra que resume tudo: 1D vs 2D

Flexbox é um modelo de layout unidimensional — você distribui itens em uma direção: linha ou coluna. Grid é bidimensional — você posiciona itens em linhas e colunas ao mesmo tempo.

Essa distinção não é marketing de especificação. Ela determina o que cada um consegue fazer de forma natural, sem hack.

Com Flexbox, quando você define flex-direction: row, os itens se organizam numa linha. Você controla espaçamento, alinhamento e wrapping — mas cada linha é independente das outras. O Flexbox não tem como fazer um item de uma linha "saber" a largura dos itens na linha de baixo.

Com Grid, você define as trilhas (colunas e linhas) e os itens se encaixam nessa grade. Uma célula na linha 2 fica perfeitamente alinhada com a célula da linha 1 porque ambas compartilham a mesma coluna.

/* Flexbox: itens em linha, sem controle de coluna entre linhas */
.nav {
  display: flex;
  gap: 16px;
  align-items: center;
}

/* Grid: layout com colunas e linhas definidas */
.page-layout {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: 64px 1fr auto;
  min-height: 100vh;
}

Quando usar Flexbox

Flexbox brilha em componentes onde o fluxo é linear e o conteúdo determina o espaço.

Bons casos de uso:

  • Barra de navegação com logo e links
  • Botão com ícone + texto lado a lado
  • Lista de tags / chips
  • Card com conteúdo empilhado verticalmente
  • Centralizar um elemento no container (o clássico justify-content: center; align-items: center)
  • Distribuir espaço entre itens com justify-content: space-between
/* centralizar vertical e horizontal — 3 linhas */
.card-center {
  display: flex;
  justify-content: center;
  align-items: center;
}

/* botão com ícone */
.btn {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* header com logo e nav em extremos opostos */
.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 24px;
}

O sinal de que Flexbox é a escolha certa: você está pensando em uma direção (ou horizontal, ou vertical), e os itens podem ter tamanhos diferentes sem problema.

O sinal de que você está forçando: você precisa que itens em linhas diferentes se alinhem entre si. Isso é o trabalho do Grid.


Quando usar CSS Grid

Grid é para layouts onde múltiplos itens precisam se alinhar em dois eixos — onde a grade importa, não só o fluxo.

Bons casos de uso:

  • Layout de página (header, sidebar, main, footer)
  • Grid de cards com altura uniforme por linha
  • Galeria de imagens
  • Dashboard com widgets em posições fixas
  • Formulários com labels e inputs alinhados em colunas
/* layout clássico de aplicação */
.app {
  display: grid;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
  grid-template-columns: 240px 1fr;
  grid-template-rows: 64px 1fr 48px;
  min-height: 100vh;
}

.header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main    { grid-area: main; }
.footer  { grid-area: footer; }
/* grid de cards responsivo sem media query */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 24px;
}

O segundo exemplo é um dos truques mais práticos do CSS moderno: auto-fill + minmax cria um grid responsivo que adiciona colunas conforme o espaço disponível, sem uma única @media query.


Combinando os dois — a abordagem real

O mais comum em projetos reais não é escolher um ou outro. É usar Grid para a estrutura macro e Flexbox para os componentes internos.

Um exemplo de layout de aplicação completo:

/* Grid define a estrutura geral da página */
.app {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: 64px 1fr;
  height: 100vh;
}

/* Flexbox organiza os itens dentro do header */
.app-header {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 24px;
}

/* Flexbox também dentro do card */
.card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px;
}

.card-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: auto; /* empurra pro fim do card */
}

O Grid não sabe (nem precisa saber) como os itens internos do header se organizam. O Flexbox não sabe (nem precisa saber) que o header ocupa grid-column: 1 / -1. Cada ferramenta faz o que faz melhor.


Por que não usar só Grid para tudo?

A tentação oposta também existe — depois de aprender Grid, usá-lo pra tudo. O problema é que Grid é mais verboso para fluxos lineares simples. Centralizar um botão com ícone com Grid:

.btn {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: 8px;
}

Versus Flexbox:

.btn {
  display: flex;
  align-items: center;
  gap: 8px;
}

Funciona nos dois, mas o Grid aqui é ruído. A intenção é menos clara — você está criando uma grade de duas colunas quando só queria alinhar dois itens em linha. Código que anuncia a intenção é mais fácil de manter.

Além disso, Grid tem comportamento menos intuitivo com conteúdo dinâmico em alguns casos — especialmente quando o número de itens varia e você quer que cada item ocupe o espaço que precisa, não uma célula da grade. Flexbox com flex-wrap é mais natural para esses casos.


Suporte a browsers: sem preocupação em 2026

Grid e Flexbox têm suporte acima de 97% em todos os browsers modernos. Se o projeto não precisa suportar IE11 (que oficialmente morreu em 2022), você pode usar qualquer feature de CSS Grid Level 2 — incluindo subgrid, que finalmente chegou ao Chrome 117 e resolveu o alinhamento de grids aninhados.

subgrid é o que você usa quando tem um container grid e quer que os itens filhos participem das trilhas do pai, em vez de criar uma grade própria:

.card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: auto;
}

.card {
  display: grid;
  grid-row: span 3;
  grid-template-rows: subgrid; /* filhos usam as trilhas do pai */
}

Isso garante que o título, a imagem e o rodapé de todos os cards fiquem na mesma linha horizontal, mesmo com conteúdo de tamanho diferente — sem JavaScript, sem altura fixa.

Se você está montando grids mais elaborados e quer visualizar o output em tempo real — CSS e Tailwind ao mesmo tempo —, uso o Gerador CSS Grid para prototipar antes de codar. Especialmente útil para testar grid-template-areas com nomes antes de commitar na estrutura final.

O post sobre HTML semântico cobre a estrutura de header, main, aside e footer — os elementos que você normalmente mapeia para as áreas do Grid. Faz sentido ler os dois juntos: semântica define o significado, Grid define o posicionamento.


Perguntas frequentes

Posso usar Flexbox e Grid no mesmo elemento?

Não diretamente — display: flex e display: grid são mutuamente exclusivos no mesmo elemento. Mas um elemento pode ser filho de um Grid e pai de um Flexbox ao mesmo tempo. Isso é exatamente o padrão de combinação descrito acima: Grid no container externo, Flexbox nos componentes internos.

CSS Grid substitui Flexbox?

Não. Eles resolvem problemas diferentes. Grid é melhor para layout de página e alinhamento bidimensional. Flexbox é melhor para fluxo linear de componentes. Na prática, você vai usar os dois — e quanto mais você usa, mais óbvio fica qual dos dois é a ferramenta certa para cada situação.

Por que meu Grid não alinha os itens da forma esperada?

A causa mais comum é não definir as trilhas explicitamente. Quando você só usa display: grid sem grid-template-columns, o browser cria uma grade de uma coluna implícita. Defina as colunas com grid-template-columns e, se necessário, as linhas com grid-template-rows. A outra causa comum é esquecer que gap não afeta as margens externas — ele só adiciona espaço entre as células.

Quando auto-fill e quando auto-fit?

auto-fill cria colunas vazias se houver espaço disponível. auto-fit expande as colunas existentes para preencher o espaço. A diferença fica visível quando você tem poucos itens: com auto-fill, as células vazias ocupam o espaço; com auto-fit, os itens existentes crescem. Para grids de cards onde você quer que os itens cresçam pra preencher a linha, auto-fit é geralmente a escolha certa.


A escolha é sobre intenção, não sobre preferência

Flexbox e Grid não são rivais — são ferramentas com escopos diferentes. A questão nunca é "qual é melhor", é "o que esse layout está tentando fazer?".

Se a resposta for "distribuir itens em uma direção, com espaçamento e alinhamento", Flexbox. Se a resposta for "posicionar elementos em uma grade com controle de linhas e colunas", Grid. Se a resposta for "estruturar a página toda", provavelmente Grid para o macro e Flexbox para os componentes.

A confusão acontece quando você usa Flexbox para fazer o trabalho de Grid — empilhando hacks de flex-wrap e width percentuais onde grid-template-columns seria três palavras. Reconhecer o padrão antes de começar a codar poupa tempo e poupa o dev que vai manter isso no futuro.

RD
Autor
Rafael Duarte
Desenvolvedor backend com passagem por fintech e SaaS B2B — trabalhou em times que escalaram APIs de zero a milhões de requisições. Carrega cicatrizes de produção suficientes para ter opiniões fortes sobre ferramentas, padrões e decisões de arquitetura. Não é acadêmico: leu a RFC do UUID quando precisou escolher entre v4 e v7 para uma tabela de alta escrita.
Ver perfil