Flexbox, Grid e Composição de Layouts para UIs em React.
Antes de você entrar nas 16 questões, vale entender o “contrato” desse bloco de exercícios: você não está só aprendendo propriedades de CSS. Você está treinando um tipo de pensamento que separa quem “arruma layout na marra” de quem constrói interfaces que se comportam bem quando o mundo real bate na porta (telas pequenas, conteúdo imprevisível, redimensionamento, itens a mais, itens a menos).
O primeiro desafio que você vai enfrentar é mental: aprender a enxergar layout como um sistema de eixos e
regras, não como tentativa-e-erro. No Flexbox, isso significa dominar o par eixo principal vs eixo
cruzado e entender que quase tudo é consequência de duas decisões: a direção (flex-direction)
e como você distribui e alinha (justify-content e align-items). Você vai lidar também
com uma das partes mais traiçoeiras do Flex: dimensionamento. flex-grow, flex-shrink e
flex-basis são o trio que define “quem ganha espaço”, “quem perde espaço” e “de onde cada item
parte” quando o container muda. Isso é exatamente o que acontece em UI mobile-first quando o conteúdo muda,
quando a tela estreita, quando o texto quebra, quando o botão precisa caber.
O segundo desafio é arquitetural: você vai sair do “um container” e entrar no mundo de layouts compostos. Os exercícios de containers aninhados treinam a habilidade de pensar em componentes: um flex container controla seus filhos diretos; cada bloco interno tem sua própria lógica. Isso é a base prática de uma UI em React bem organizada, porque React é composição: blocos dentro de blocos, cada um com responsabilidades claras.
O terceiro desafio é de precisão visual e usabilidade: centralização e distribuição de espaço não são
“firulas”; são o que faz um layout parecer intencional em vez de improvisado. Ao dominar centralização
horizontal e vertical, e padrões de espaçamento como space-between e space-around, você
ganha controle sobre hierarquia e respiro visual, e aprende a evitar o erro comum de “resolver com margin
aleatória até parecer certo”.
Por fim, você vai encarar o Grid. Aqui o desafio muda: em vez de um eixo principal, você trabalha com uma malha 2D de linhas e colunas. Você vai aprender a declarar trilhos (tracks), preencher células e controlar o “span” (itens ocupando múltiplas colunas/linhas). E vai perceber a diferença real entre Flex e Grid: Flex é ótimo para distribuir itens em uma direção; Grid é o canivete suíço quando o layout é naturalmente bidimensional.
Se você conseguir resolver todas as questões, as competências que você terá dominado são bem objetivas: você será capaz de “ler” e depurar layouts, dominar a lógica de eixos no Flexbox, controlar crescimento/encolhimento de itens sob restrição de espaço, alinhar e distribuir elementos com intenção e compor layouts mais complexos com containers aninhados: o tipo de raciocínio que vira componente reutilizável em React.
Além disso, você desenvolve previsibilidade: suas UIs continuam funcionando quando muda o tamanho da tela, quando entra mais conteúdo, quando um item some, quando a interface precisa se adaptar. Isso é a essência de um pensamento mobile-first: não é “deixar bonito no meu monitor”; é fazer o layout sobreviver a variações.
Ao fim e ao cabo, os desafios adiante vão te forçar a trocar tentativa-e-erro por método. Se você vencer todos, você sai
com o kit fundamental para construir interfaces responsivas com confiança: controle de direção e alinhamento no
Flexbox, controle de dimensionamento com grow/shrink/basis, composição de layouts com containers
aninhados, centralização robusta e domínio inicial de Grid para layouts 2D. A partir daí, qualquer UI em React
fica menos “mágica” e mais engenharia.
index.html no navegador).
A ideia aqui é aprender “com evidência”: você cola o código, abre, redimensiona a janela e observa o
comportamento. Em todos os exercícios, ative o overlay de Flex/Grid no DevTools e redimensione a viewport.
flex-direction define o eixo principal (main axis) e o sentido.justify-content alinha/distribui no eixo principal.align-items alinha no eixo cruzado (cross axis).flex: grow shrink basis controla como cada item cresce/encolhe/parte de uma base.row-reverse mantém o eixo principal horizontal, mas inverte a ordem visual.<div class="container ex1">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
<style>
.container { display: flex; gap: 8px; padding: 12px; border: 1px solid #999; }
.item { padding: 12px; border: 1px solid #666; }
.ex1 { flex-direction: row-reverse; }
</style>
Checkpoint: você deve ver “3 2 1” da esquerda para a direita.
column-reverse inverte de cima para baixo.<div class="container ex2">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
</div>
<style>
.container { display: flex; gap: 8px; padding: 12px; border: 1px solid #999; }
.item { padding: 12px; border: 1px solid #666; }
.ex2 { flex-direction: column-reverse; }
</style>
Checkpoint: você deve ver “4” no topo e “1” no final.
Lembrete: flex é um “combo”: flex: grow shrink basis;. Esses três números definem a negociação de espaço entre os itens quando o container muda de tamanho.
flex-grow maior ao primeiro item.<div class="container ex3">
<div class="item a">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
<style>
.container { display:flex; gap:8px; padding:12px; border:1px solid #999; width: 800px; }
.item { padding:12px; border:1px solid #666; flex: 1 1 0; } /* todos crescem igual */
.ex3 .a { flex-grow: 3; } /* item 1 cresce mais */
</style>
Checkpoint: ao aumentar/diminuir a largura do container, o item “1” leva mais espaço.
flex-shrink fazer efeito, tem que faltar espaço. Então forçamos overflow horizontal.<div class="container ex4">
<div class="item">1</div>
<div class="item">2</div>
<div class="item c">3</div>
<div class="item">4</div>
</div>
<style>
.container { display:flex; gap:8px; padding:12px; border:1px solid #999; width: 420px; }
.item { padding:12px; border:1px solid #666; flex: 0 1 200px; } /* base grande -> vai precisar encolher */
.ex4 .c { flex-shrink: 0; } /* item 3 tenta não encolher */
</style>
Checkpoint: reduza a largura (ou mantenha 420px): o item “3” fica mais “inteiro” que os outros.
flex-basis é a “largura/altura inicial” no eixo principal antes de grow/shrink.<div class="container ex5">
<div class="item">1</div>
<div class="item b">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
</div>
<style>
.container { display:flex; gap:8px; padding:12px; border:1px solid #999; width: 900px; }
.item { padding:12px; border:1px solid #666; flex: 0 1 auto; }
.ex5 .b { flex-basis: 200px; }
</style>
Checkpoint: o item “2” começa “maior” (base 200px), os outros seguem “auto”.
Regra rápida (para flex-direction: row): eixo principal é horizontal. justify-content mexe no horizontal; align-items mexe no vertical. Para enxergar bem o eixo cruzado, defina uma altura no container.
<div class="container ex6">
<div class="item">1</div><div class="item">2</div><div class="item">3</div><div class="item">4</div><div class="item">5</div>
</div>
<style>
.container { display:flex; gap:8px; padding:12px; border:1px solid #999; height: 160px; }
.item { padding:12px; border:1px solid #666; }
.ex6 { justify-content: flex-start; align-items: flex-start; }
</style>
Checkpoint: tudo “grudado” no canto superior esquerdo.
<div class="container ex7">
<div class="item">1</div><div class="item">2</div><div class="item">3</div><div class="item">4</div>
</div>
<style>
.container { display:flex; gap:8px; padding:12px; border:1px solid #999; height: 160px; }
.item { padding:12px; border:1px solid #666; }
.ex7 { justify-content: flex-end; align-items: flex-end; }
</style>
Checkpoint: tudo “grudado” no canto inferior direito.
<div class="container ex8">
<div class="item">1</div><div class="item">2</div><div class="item">3</div>
</div>
<style>
.container { display:flex; gap:8px; padding:12px; border:1px solid #999; width: 700px; }
.item { padding:12px; border:1px solid #666; }
.ex8 { justify-content: center; }
</style>
Checkpoint: o grupo fica no meio horizontal do container.
<div class="container ex9">
<div class="item">1</div><div class="item">2</div><div class="item">3</div><div class="item">4</div><div class="item">5</div><div class="item">6</div>
</div>
<style>
.container { display:flex; padding:12px; border:1px solid #999; width: 900px; }
.item { padding:12px; border:1px solid #666; }
.ex9 { justify-content: space-between; }
</style>
Checkpoint: primeiro encosta à esquerda, último à direita, e o espaço vira gaps distribuídos.
Observação útil: align-items: stretch (padrão) fica evidente quando os itens não têm altura definida.
<div class="outer ex10">
<div class="inner">
<div class="item">A1</div><div class="item">A2</div><div class="item">A3</div>
</div>
<div class="inner">
<div class="item">B1</div><div class="item">B2</div><div class="item">B3</div>
</div>
</div>
<style>
.outer { display:flex; gap:16px; padding:12px; border:1px solid #999; }
.inner { display:flex; flex-direction: column; gap:8px; padding:12px; border:1px dashed #666; }
.item { padding:10px; border:1px solid #666; }
.ex10 { flex-direction: row; }
</style>
Checkpoint: dois blocos lado a lado; dentro de cada bloco, três itens empilhados.
<div class="outer ex11">
<div class="inner">
<div class="item">1</div><div class="item">2</div><div class="item">3</div><div class="item">4</div>
</div>
<div class="inner">
<div class="item">5</div><div class="item">6</div><div class="item">7</div><div class="item">8</div>
</div>
<div class="inner">
<div class="item">9</div><div class="item">10</div><div class="item">11</div><div class="item">12</div>
</div>
</div>
<style>
.outer { display:flex; flex-direction: column; gap:16px; padding:12px; border:1px solid #999; }
.inner { display:flex; flex-direction: row; gap:8px; padding:12px; border:1px dashed #666; }
.item { padding:10px; border:1px solid #666; }
</style>
Checkpoint: três “linhas” empilhadas; cada linha com quatro itens horizontais.
justify-content + align-items.<div class="container ex12">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
<style>
.container { display:flex; border:1px solid #999; height: 240px; }
.item { padding:12px; border:1px solid #666; }
.ex12 { justify-content: center; align-items: center; gap: 8px; }
</style>
Checkpoint: o conjunto fica no meio da caixa, tanto no X quanto no Y.
space-around cria “ar” ao redor de cada item (bordas com metade do espaço interno).<div class="container ex13">
<div class="item">1</div><div class="item">2</div><div class="item">3</div><div class="item">4</div>
</div>
<style>
.container { display:flex; border:1px solid #999; width: 900px; padding: 12px 0; }
.item { padding:12px; border:1px solid #666; }
.ex13 { justify-content: space-around; }
</style>
Checkpoint: espaços “em volta” de cada item; bordas não ficam coladas.
grid-column e grid-row. A unidade fr distribui o espaço restante proporcionalmente.
<div class="grid ex14">
<div class="cell">1</div><div class="cell">2</div><div class="cell">3</div><div class="cell">4</div>
<div class="cell">5</div><div class="cell">6</div><div class="cell">7</div><div class="cell">8</div>
<div class="cell">9</div><div class="cell">10</div><div class="cell">11</div><div class="cell">12</div>
</div>
<style>
.grid { display:grid; gap:8px; padding:12px; border:1px solid #999; }
.cell { padding:12px; border:1px solid #666; }
.ex14 { grid-template-columns: repeat(4, 1fr); grid-template-rows: repeat(3, 80px); }
</style>
Checkpoint: 4 colunas, 3 linhas, tudo preenchido.
<div class="grid ex15">
<div class="cell a">1</div>
<div class="cell b">2</div>
<div class="cell">3</div>
<div class="cell">4</div>
<div class="cell">5</div>
<div class="cell">6</div>
</div>
<style>
.grid { display:grid; gap:8px; padding:12px; border:1px solid #999; }
.cell { padding:12px; border:1px solid #666; }
.ex15 { grid-template-columns: repeat(3, 1fr); grid-auto-rows: 80px; }
.ex15 .a { grid-column: 1 / span 2; } /* duas colunas */
.ex15 .b { grid-row: 1 / span 2; } /* duas linhas */
</style>
Checkpoint: o “1” fica largo (2 colunas). O “2” fica alto (2 linhas).
<div class="grid ex16">
<div class="cell">1</div><div class="cell">2</div><div class="cell">3</div>
<div class="cell">4</div><div class="cell">5</div><div class="cell">6</div>
<div class="cell">7</div><div class="cell">8</div><div class="cell">9</div>
</div>
<style>
.grid { display:grid; gap:8px; padding:12px; border:1px solid #999; }
.cell { padding:12px; border:1px solid #666; }
.ex16 {
grid-template-columns: 1fr 2fr 1fr;
grid-template-rows: repeat(3, 80px);
}
</style>
Checkpoint: a coluna do meio fica visivelmente mais larga.
repeat(auto-fit, minmax(...))).