Mobile & React

Flexbox, Grid e Composição de Layouts para UIs em React.

Por Fábio Linhares • Instituto Infnet

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.

Vou assumir que você já sabe o básico de HTML/CSS (tags, classes, abrir um 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.
BLOCO 01
Contrato do TP e Exercícios 1–2 (flex-direction)
Objetivo: estabelecer o modelo mental de eixos no Flexbox e praticar direções básica/ reversa.
Modelo mental de Flexbox
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.
Exercício 1 — row + inverter ordem
O 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.

Exercício 2 — column + inverter ordem
Agora o eixo principal é vertical. 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.

BLOCO 02
Exercícios 3–5 (flex-grow, flex-shrink, flex-basis)
Objetivo: controlar quem cresce, quem encolhe e qual a base de cada item.

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.

Exercício 3 — o item 1 cresce mais
Faça o container largo e dê 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.

Exercício 4 — o item 3 encolhe menos
Para 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.

Exercício 5 — flex-basis 200px no item 2
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”.

BLOCO 03
Exercícios 6–9 (alinhamento e espaçamento)
Objetivo: praticar flex-start, flex-end, center, space-between e space-around.

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.

Exercício 6 — itens no início
<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.

Exercício 7 — itens no final
<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.

Exercício 8 — centralizar horizontalmente
<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.

Exercício 9 — space-between
<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.

BLOCO 04
Exercícios 10–11 (flex containers aninhados)
Objetivo: pensar em componentes usando flex dentro de flex.
Regra mental que salva: um flex container controla apenas seus filhos diretos. Um layout complexo nada mais é do que vários flex containers aninhados.
Exercício 10 — externo em row; internos em column
<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.

Exercício 11 — externo em column; internos em row
<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.

BLOCO 05
Exercícios 12–13 (centralização e distribuição)
Objetivo: centralizar robustamente e dominar space-around.
Exercício 12 — centralizar horizontal e vertical
Clássico de entrevista: 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.

Exercício 13 — space-around
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.

BLOCO 06
Exercícios 14–16 (Grid Layout e debrief)
Objetivo: declarar trilhos, controlar spans e fechar com um debrief integrando Flex + Grid.
Modelo mental de Grid: você define trilhos (colunas/linhas), os itens preenchem células e podem ocupar múltiplos trilhos com grid-column e grid-row. A unidade fr distribui o espaço restante proporcionalmente.
Exercício 14 — 4 colunas × 3 linhas, preencher tudo
12 células → 12 itens.
<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.

Exercício 15 — item 1 ocupa 2 colunas; item 2 ocupa 2 linhas
<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).

Exercício 16 — 3 colunas × 3 linhas, larguras diferentes
<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.

Debrief final (exercício deliberado)
Crie um layout mobile-first misturando Flex + Grid com:
• Um header fixo com botão e título (Flex).
• Uma lista de cards responsivos (Grid com repeat(auto-fit, minmax(...))).
Valide: teclado funciona, foco visível, cards não pulam (sem CLS) e nada quebra em 320px.