Alguns anos atrás, sentei-me para construir um dashboard. Nada sofisticado — apenas uma sidebar fixa, uma área de conteúdo principal e um rodapé. O Flexbox parecia a escolha óbvia e, a princípio, funcionou. Então, adicionei uma linha de cards na seção principal. O layout inteiro desmoronou. Passei as três horas seguintes lutando com proporções de flex-grow e larguras percentuais aninhadas, vendo containers se recusarem a alinhar, não importa quanto padding eu subtraísse. A página parecia uma torre prestes a cair.

Essa experiência dolorosa me ensinou a coisa mais importante sobre o layout moderno de CSS: Flexbox e Grid não são rivais. Eles são ferramentas para trabalhos diferentes, e a maioria dos layouts que falham acontece por escolher a ferramenta errada.

A Diferença é Dimensional

Pense no Flexbox como um corredor. Os itens fluem em uma única direção, seja como uma linha ou como uma coluna. Ele foi construído para distribuição unidimensional. O navegador analisa o conteúdo e então decide como esticá-lo, encolhê-lo ou alinhá-lo ao longo desse eixo único. Isso torna o Flexbox perfeito para situações onde o conteúdo dita o layout. Uma barra de navegação, uma pilha de campos de formulário ou um conjunto de tags que precisam de espaçamento igual se acomodam naturalmente em um container flex, pois compartilham uma única linha de lógica.

O Grid, por outro lado, é uma planta baixa. Ele é estritamente bidimensional, lidando com linhas e colunas ao mesmo tempo. Você define a estrutura primeiro e depois posiciona os itens dentro dela. Isso torna o Grid ideal para a arquitetura geral da página — qualquer lugar onde você precise controlar o posicionamento vertical e horizontal simultaneamente. Quando você tenta forçar um design bidimensional complexo através de containers Flexbox aninhados, acaba com um markup profundo, wrappers frágeis e cálculos instáveis que desmoronam no momento em que você adiciona um elemento extra.

O Flexbox Ainda tem seu Valor

Não tenha pressa em substituir cada container flex por Grid. Dentro de componentes individuais, o Flexbox costuma ser mais limpo e direto. Se você tem o rodapé de um card com dois botões e quer um alinhado à esquerda e outro à direita, justify-content: space-between faz exatamente o que você deseja. Se precisar centralizar verticalmente um ícone dentro de um botão de altura desconhecida, align-items: center é o caminho mais simples. Conteúdo variável — como uma linha de badges de usuário com diferentes comprimentos de nome — encaixa-se confortavelmente no Flexbox porque ele prioriza o conteúdo. O container se adapta ao que ele contém.

O Grid prioriza o container. Você diz ao navegador quantos tracks existem e qual deve ser o tamanho deles, e então solta os itens nessas células. Se o seu layout for apenas uma única linha de elementos irmãos compartilhando espaço, o Grid adiciona uma complexidade desnecessária.

O Layout da Página pertence ao Grid

É aqui que o Grid assume o controle. Lembra do meu pesadelo com o dashboard? Veja como a estrutura deveria ter sido desde o início:

.page {
  display: grid;
  min-height: 100vh;
  grid-template-rows: auto 1fr auto;
  grid-template-columns: 200px 1fr;
}

.header { grid-row: 1; grid-column: 1 / -1; }
.sidebar { grid-row: 2; grid-column: 1; }
.main { grid-row: 2; grid-column: 2; }
.footer { grid-row: 3; grid-column: 1 / -1; }

Observe o que está acontecendo. O container .page estabelece três linhas e duas colunas. A primeira linha ajusta seu tamanho ao que quer que o header contenha graças ao auto. A linha do meio reivindica todo o espaço restante disponível com 1fr. O rodapé fica na última linha, dimensionado de acordo com seu próprio conteúdo. Enquanto isso, a sidebar trava em 200 pixels de largura, e a área principal preenche o restante.

A lógica de posicionamento é o verdadeiro alívio. O header se estende da linha de coluna 1 até a linha -1, o que significa que ele se estende por ambas as colunas, independentemente de quantas colunas você adicione depois. A sidebar e o conteúdo principal compartilham a linha 2, mas ocupam colunas separadas. O rodapé retorna à largura total na linha 3. Você não precisa de cálculos de porcentagem nos elementos filhos. Você não precisa de wrappers aninhados lutando por altura. Mude a largura da sidebar em um único lugar e a área principal se ajustará automaticamente. O layout inteiro respira como um sistema único.

Legibilidade com grid-template-areas

Para ainda mais clareza, você pode nomear suas seções. Em vez de gerenciar números de linha, você escreve um mapa visual:

.page {
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
}

.header { grid-area: header; }
.main { grid-area: main; }

Agora sua folha de estilo parece um wireframe. Se algum dia você quiser que a sidebar apareça à direita em um breakpoint diferente, basta trocar duas palavras na string do template. Esse tipo de legibilidade estrutural é impossível de alcançar dentro de uma torre de containers flex aninhados.

Duas Lições Difíceis

O Grid não é mágica. Existem dois erros que arruinarão seu layout rapidamente.

O primeiro é o uso descuidado de unidades. Se você definir grid-template-columns: 1fr 1fr 1fr, mas o seu design precisar de apenas duas colunas de conteúdo, aquela terceira trilha ainda existirá. Ela ficará vazia, criando um espaço que você não esperava, ou forçará o seu conteúdo real a se espremer de formas que quebrem o seu design. Seja intencional. Quando você quiser dizer duas colunas, escreva repeat(2, 1fr).