Mobile-first UI com React: Imagens, Layout e Contexto
Roteiro com picture, img fluida, Flexbox, Grid, viewport e media queries por contexto
À primeira vista, este conjunto parece apenas uma sequência de exercícios de HTML e CSS. Não é. Ele cobra a passagem do “eu consigo montar algo que parece funcionar” para o “eu consigo interpretar um requisito, escolher a técnica correta, implementar com critério, testar em cenários diferentes e explicar por que a solução funciona”.
O percurso passa por cinco decisões centrais: escolher entre picture e img fluida, escolher entre Flexbox e Grid, tratar viewport e media queries como sistema, adaptar a interface ao contexto de interação e traduzir wireframe em estrutura funcional.
Leia cada exercício como um pequeno laboratório. O objetivo não é decorar propriedade solta; é aprender a transformar requisito em estrutura, condição e comportamento observável.
O que o enunciado pede
Usar picture com três saídas: até 576px, até 992px e acima disso, sempre ocupando 100% da largura do viewport.
Conceito cobrado
Escolha correta entre troca real de arquivo e simples fluidez visual.
Estrutura dos dados
HTML mínimo: um picture, dois source com media/srcset e um img fallback.
<!-- index.html -->
<picture class="hero-picture">
<source media="(max-width: 576px)" srcset="img-small.jpg">
<source media="(max-width: 992px)" srcset="img-medium.jpg">
<img src="img-large.jpg" alt="Imagem responsiva">
</picture>
/* styles.css */
.hero-picture,
.hero-picture img {
width: 100vw;
height: auto;
}Como pensar
Se o requisito muda a imagem entregue por faixa de tela, a técnica correta é picture, não só img fluida.
Como validar
Reduza e aumente a largura da tela. A imagem deve continuar ocupando a largura visível, e o arquivo deve mudar conforme o breakpoint.
Tabela de Evidência
- Até 576px -> carrega
img-small.jpg. - 577px a 992px -> carrega
img-medium.jpg. - Acima de 992px -> usa o
imgfallback.
Variáveis-chave
mediasrcsetwidth: 100vw
Como explicar
Usei picture porque o enunciado pede arquivos diferentes por faixa. O img final funciona como fallback e cobre a última resolução.
Erro comum
Usar só img com max-width: 100%. Isso deixa a imagem fluida, mas não troca o arquivo.
O que o enunciado pede
Usar a tag img e CSS para que a imagem ocupe a largura visível sem distorção.
Conceito cobrado
Diferença entre imagem fluida e troca de arquivo.
Estrutura dos dados
HTML mínimo: uma única img com classe dedicada.
<!-- index.html -->
<img class="hero-img" src="img.jpg" alt="Imagem responsiva">
/* styles.css */
.hero-img {
width: 100vw;
max-width: 100%;
height: auto;
}Como pensar
Aqui a mídia é a mesma. O trabalho do CSS é só fazer a imagem se adaptar sem overflow nem deformação.
Como validar
A imagem precisa continuar proporcional em qualquer largura e não pode estourar horizontalmente.
Tabela de Evidência
- 320px -> imagem ocupa a largura visível.
- 768px -> continua proporcional.
- Sem barra horizontal ->
max-width: 100%cumpriu o papel.
Variáveis-chave
width: 100vwmax-width: 100%height: auto
Como explicar
Usei img porque o enunciado não pede troca de arquivo. width: 100vw ocupa a largura visível e height: auto preserva a proporção.
Erro comum
Confundir este caso com picture e complicar uma questão que só pede imagem fluida.
O que o enunciado pede
Reproduzir um layout mobile com ícone de menu, avatar circular, título, parágrafo e botão usando Flexbox.
Conceito cobrado
Flexbox para fluxo vertical e alinhamento em um eixo.
Estrutura dos dados
HTML mínimo: container .profile-card, .menu-icon, .avatar, título, parágrafo e botão.
<!-- index.html -->
<div class="profile-card">
<div class="menu-icon">☰</div>
<img class="avatar" src="avatar.jpg" alt="Foto de John">
<h1>Hi, I am John,<br>Creative Technologist</h1>
<p>Amet minim mollit non deserunt ullamco est sit aliqua dolor do amet sint.</p>
<a class="btn" href="#">Download Resume</a>
</div>
/* styles.css */
.profile-card {
width: 100vw;
max-width: 576px;
min-height: 100vh;
margin: 0 auto;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 1rem;
padding: 2rem 1.5rem;
text-align: center;
}
.menu-icon { align-self: flex-end; font-size: 1.5rem; }
.avatar {
width: 120px;
aspect-ratio: 1 / 1;
border-radius: 50%;
object-fit: cover;
}Como pensar
O eixo dominante é vertical. Isso pede Flexbox em coluna, não Grid e nem posicionamento absoluto.
Como validar
Entre 360px e 576px, tudo precisa ficar empilhado, centralizado e sem scroll horizontal.
Tabela de Evidência
- 360px -> ícone, avatar, texto e botão empilhados.
- 576px -> card continua centralizado.
- Sem scroll horizontal -> largura e padding estão sob controle.
Variáveis-chave
flex-direction: columnalign-self: flex-endmax-width: 576px
Como explicar
Usei Flexbox em coluna porque o protótipo é vertical. O ícone foi jogado para a direita com align-self, e o card respeita a faixa mobile pedida.
Erro comum
Tentar resolver com coordenadas absolutas e perder o fluxo natural do layout.
O que o enunciado pede
Pegar a estrutura do exercício anterior e reorganizar o layout a partir de 992px com media query.
Conceito cobrado
Progressive enhancement com Flexbox e min-width.
Estrutura dos dados
HTML mínimo: navegação .top-nav e hero com dois blocos, .hero-text e .hero-image.
<!-- index.html -->
<div class="page">
<nav class="top-nav">
<a href="#">Works</a>
<a href="#">Blog</a>
<a href="#">Contact</a>
</nav>
<section class="hero">
<div class="hero-text">
<h1>Hi, I am John,<br>Creative Technologist</h1>
<p>Amet minim mollit non deserunt ullamco est sit aliqua dolor do amet sint.</p>
<a class="btn" href="#">Download Resume</a>
</div>
<div class="hero-image">
<img class="avatar" src="avatar.jpg" alt="Foto de John">
</div>
</section>
</div>
/* styles.css */
.top-nav, .hero { display: flex; }
.top-nav { flex-direction: column; gap: .75rem; align-items: center; }
.hero { flex-direction: column; gap: 1.5rem; align-items: center; }
.hero-text, .hero-image { width: 100%; text-align: center; }
@media (min-width: 992px) {
.top-nav { flex-direction: row; justify-content: center; }
.hero { flex-direction: row; justify-content: space-between; align-items: center; }
.hero-text, .hero-image { width: 48%; text-align: left; }
}Como pensar
O layout base continua mobile-first. A media query só reorganiza o que já existia, em vez de criar outra página.
Como validar
Abaixo de 992px tudo empilha. A partir daí, hero e navegação precisam virar linha.
Tabela de Evidência
- 768px -> menu e hero em coluna.
- 992px -> menu em linha.
- 992px+ -> texto e imagem lado a lado.
Variáveis-chave
flex-directionmin-width: 992pxwidth: 48%
Como explicar
A solução nasce mobile-first e a media query de 992px só redistribui os blocos. Isso deixa o CSS incremental e previsível.
Erro comum
Começar pelo desktop e tentar “encolher” depois, acumulando exceções.
O que o enunciado pede
Um container com três filhos centralizados vertical e horizontalmente, ocupando a altura da tela e se adaptando no mobile.
Conceito cobrado
Grid para centralização e fluxo automático.
Estrutura dos dados
HTML mínimo: um .container com três filhos, por exemplo .b1, .b2 e .b3.
<!-- index.html -->
<div class="container">
<div class="box b1"></div>
<div class="box b2"></div>
<div class="box b3"></div>
</div>
/* styles.css */
.container {
min-height: 100vh;
display: grid;
place-items: center;
grid-auto-flow: column;
gap: 1rem;
}
@media (max-width: 576px) {
.container { grid-auto-flow: row; }
}Como pensar
A exigência é centralizar no eixo vertical e horizontal ao mesmo tempo. place-items resolve isso de forma direta.
Como validar
Os três filhos precisam ficar centralizados na tela. No mobile, devem passar de horizontal para vertical.
Tabela de Evidência
- Desktop -> três filhos no centro, lado a lado.
- Até 576px -> filhos empilhados.
- Altura da tela ocupada ->
min-height: 100vh.
Variáveis-chave
display: gridplace-items: centergrid-auto-flow
Como explicar
Usei Grid porque queria centralização bidimensional simples e um fluxo que pudesse trocar de coluna para linha no mobile.
Erro comum
Responder com Flexbox sem perceber que a própria questão pede Grid.
O que o enunciado pede
Um layout com header, nav, main, aside e footer em 3 colunas e ao menos 3 linhas.
Conceito cobrado
Grid para áreas e spans entre colunas.
Estrutura dos dados
HTML mínimo: um container .layout contendo exatamente header, nav, main, aside e footer.
<!-- index.html -->
<div class="layout">
<header>Header</header>
<nav>Nav</nav>
<main>Main</main>
<aside>Aside</aside>
<footer>Footer</footer>
</div>
/* styles.css */
.layout {
min-height: 100vh;
display: grid;
grid-template-columns: 220px 1fr 220px;
grid-template-rows: auto 1fr auto;
gap: 12px;
}
header { grid-column: 1 / -1; }
nav { grid-column: 1; }
main { grid-column: 2; }
aside { grid-column: 3; }
footer { grid-column: 1 / -1; }Como pensar
O problema é claramente bidimensional: há linhas, colunas e elementos ocupando toda a largura em cima e embaixo.
Como validar
Header e footer devem atravessar as três colunas; nav, main e aside ficam lado a lado no meio.
Tabela de Evidência
- Header ->
grid-column: 1 / -1. - Footer ->
grid-column: 1 / -1. - Miolo -> nav na 1, main na 2, aside na 3.
Variáveis-chave
grid-template-columnsgrid-template-rowsgrid-column
Como explicar
Usei Grid porque a página precisa de áreas em linhas e colunas. Header e footer ocupam toda a largura, e o miolo fica distribuído por coluna.
Erro comum
Criar tudo com Flexbox e depois forçar spans que o Grid resolveria de forma natural.
O que o enunciado pede
Reutilizar o arquivo anterior, incluir a meta viewport, alterar condições e escrever três observações no main.
Conceito cobrado
Viewport como interpretação inicial de largura e zoom, não como detalhe decorativo.
Estrutura dos dados
HTML mínimo: a meta tag no head e um main com três parágrafos curtos de observação.
<!-- index.html -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<main>
<p>Sem a meta viewport, a página parece encolhida em dispositivos móveis porque o navegador assume uma largura virtual maior.</p>
<p>Ao alterar <code>initial-scale</code>, o zoom inicial muda e a leitura começa mais ampliada ou mais afastada.</p>
<p>Ao testar combinações como <code>width=500</code> ou <code>initial-scale=2</code>, a interface passa a ser percebida com outra referência de largura e escala.</p>
</main>Como pensar
Aqui a resposta não é só técnica de CSS. É experimento controlado: mudar condição, observar e explicar o efeito.
Como validar
Abra o Device Toolbar, compare com e sem a meta tag e altere initial-scale para confirmar a mudança de percepção inicial.
Tabela de Evidência
- Sem meta viewport -> página “encolhida”.
initial-scale=2-> abertura mais ampliada.width=500-> outra referência inicial de largura.
Variáveis-chave
width=device-widthinitial-scale- Device Toolbar
Como explicar
A meta viewport informa ao navegador móvel como interpretar largura e zoom inicial. Ao mudá-la, eu mudo a forma como a página aparece logo na abertura.
Erro comum
Tratar a questão como se bastasse copiar a meta tag sem observar nem redigir o efeito percebido.
O que o enunciado pede
Criar um arquivo CSS com cinco breakpoints do menor para o maior, em lógica mobile-first.
Conceito cobrado
Crescimento incremental com min-width.
Estrutura dos dados
Estrutura mínima: um arquivo CSS com base sem media query e cinco media queries em ordem crescente.
/* styles.css */
/* base: mobile pequeno */
@media (min-width: 360px) { }
@media (min-width: 576px) { }
@media (min-width: 768px) { }
@media (min-width: 992px) { }
@media (min-width: 1200px) { }Como pensar
O layout nasce sem media query. Cada breakpoint só acrescenta comportamento quando a largura cresce.
Como validar
Verifique que os breakpoints estão em ordem crescente e que a base sem media query representa o cenário menor.
Tabela de Evidência
- Base -> mobile pequeno.
- 768px -> estado tablet.
- 1200px -> estado desktop maior.
Variáveis-chave
min-width- ordem crescente
- base sem media query
Como explicar
Comecei sem media query e fui ampliando com min-width. Isso é mobile-first de verdade, porque o layout cresce sem inverter a lógica.
Erro comum
Misturar max-width e min-width sem critério e perder a progressão incremental.
O que o enunciado pede
Três CSS chamados por <link>, sendo um deles específico para impressão.
Conceito cobrado
Carga condicional de CSS pelo atributo media.
Estrutura dos dados
HTML mínimo: três tags link, cada uma com um arquivo e uma condição de mídia.
<!-- index.html -->
<link rel="stylesheet" href="screen-small.css" media="screen and (max-width: 767px)">
<link rel="stylesheet" href="screen-large.css" media="screen and (min-width: 768px)">
<link rel="stylesheet" href="print.css" media="print">Como pensar
A decisão aqui é separar o CSS no próprio carregamento, e não usar um arquivo único com tudo misturado.
Como validar
Inspecione o HTML e confirme que cada link está condicionado ao cenário correto: tela pequena, tela grande e impressão.
Tabela de Evidência
screen-small.css->max-width: 767px.screen-large.css->min-width: 768px.print.css->media="print".
Variáveis-chave
<link>mediaprint
Como explicar
Usei o atributo media na própria tag link, então o navegador decide quando cada arquivo entra em cena.
Erro comum
Criar três arquivos mas carregar todos sem condição, perdendo o objetivo da questão.
O que o enunciado pede
Três chamadas com @import, combinando condições com and e alternativa equivalente a “ou”.
Conceito cobrado
Consultas de mídia compostas em CSS.
Estrutura dos dados
Estrutura mínima: um arquivo CSS com três linhas @import e combinações claras de condição.
/* styles.css */
@import url("portrait.css") screen and (orientation: portrait);
@import url("wide.css") screen and (min-width: 992px) and (min-height: 700px);
@import url("combo.css") screen and (orientation: landscape), screen and (min-width: 1200px);Como pensar
Em CSS, o “ou” não é a palavra or; ele é representado por vírgula.
Como validar
Cheque se há pelo menos uma combinação com and e uma alternativa separada por vírgula.
Tabela de Evidência
- Import 1 -> orientação portrait.
- Import 2 -> largura mínima + altura mínima.
- Import 3 -> landscape ou tela bem larga.
Variáveis-chave
@importand- vírgula como alternativa
Como explicar
Usei and para combinar condições na mesma consulta e vírgula para representar alternativas equivalentes a “ou”.
Erro comum
Escrever or literalmente, como se CSS aceitasse a palavra.
O que o enunciado pede
Um layout vertical por padrão e horizontal quando houver largura suficiente.
Conceito cobrado
Flexbox com mudança de direção por breakpoint.
Estrutura dos dados
HTML mínimo: um wrapper com uma imagem e um bloco de texto.
<!-- index.html -->
<div class="wrap">
<img class="hero" src="img.jpg" alt="Imagem">
<div class="text">
<h1>Responsividade</h1>
<p>Uma interface responsiva melhora leitura, uso e adaptação.</p>
</div>
</div>
/* styles.css */
.wrap { display: flex; flex-direction: column; gap: 1rem; }
.hero { width: 100%; height: auto; }
@media (min-width: 768px) {
.wrap { flex-direction: row; align-items: center; }
.hero, .text { width: 50%; }
}Como pensar
A mesma estrutura HTML deve servir aos dois estados. A media query só muda a direção do fluxo.
Como validar
No mobile, imagem e texto ficam empilhados. A partir do breakpoint, os dois blocos ficam lado a lado.
Tabela de Evidência
- 375px -> imagem em cima, texto embaixo.
- 768px -> dois blocos na mesma linha.
- Sem duplicar HTML -> a estrutura continua única.
Variáveis-chave
flex-directionmin-width: 768pxwidth: 50%
Como explicar
Começo em coluna porque o padrão é mobile-first. Quando a largura cresce, a media query vira o layout para linha.
Erro comum
Criar dois HTMLs diferentes, um para mobile e outro para desktop.
O que o enunciado pede
Uma página simples com texto e imagem, em light e dark, sem CSS inline.
Conceito cobrado
Tokens de cor com prefers-color-scheme.
Estrutura dos dados
HTML mínimo: um container .card com título, imagem e parágrafo.
<!-- index.html -->
<div class="card">
<h1>Benefícios da responsividade</h1>
<img src="img.jpg" alt="Interface responsiva">
<p>Sites responsivos melhoram leitura, navegação e adaptação entre dispositivos.</p>
</div>
/* styles.css */
:root {
--bg: #ffffff;
--fg: #111111;
--card: #f1f3f5;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #111111;
--fg: #f8f9fa;
--card: #1c1f24;
}
}
body { background: var(--bg); color: var(--fg); }
.card { background: var(--card); padding: 1rem; border-radius: 12px; }Como pensar
A estrutura HTML não muda. O tema troca apenas os tokens de cor no CSS.
Como validar
Force light e dark no navegador e confira se texto e imagem continuam legíveis com o mesmo HTML.
Tabela de Evidência
- Light -> fundo claro, texto escuro.
- Dark -> fundo escuro, texto claro.
- Mesmo HTML -> só os tokens mudam.
Variáveis-chave
:rootprefers-color-scheme--bg,--fg,--card
Como explicar
Usei variáveis CSS para centralizar a paleta. O prefers-color-scheme troca só os tokens, então o restante continua consistente.
Erro comum
Duplicar um bloco grande de CSS inteiro em vez de trocar só as cores.
O que o enunciado pede
Três botões com aparência diferente conforme pointer: none, coarse e fine.
Conceito cobrado
Adaptação por precisão do dispositivo de entrada.
Estrutura dos dados
HTML mínimo: um wrapper com três button.
<!-- index.html -->
<div class="buttons">
<button>Botão 1</button>
<button>Botão 2</button>
<button>Botão 3</button>
</div>
/* styles.css */
.buttons { display: flex; gap: 1rem; padding: 1rem; }
button { padding: 1rem 1.25rem; border: 0; border-radius: 10px; }
@media (pointer: none) { button { background: #adb5bd; color: #111; } }
@media (pointer: coarse) { button { background: #74c0fc; font-size: 1.1rem; } }
@media (pointer: fine) { button { background: #51cf66; cursor: pointer; } }Como pensar
pointer fala da precisão do dispositivo de entrada. A interface deve deixar essa diferença evidente.
Como validar
Em um contexto fino, os botões mostram cursor; em coarse, ficam maiores; em none, ficam neutros e sem depender de ponteiro.
Tabela de Evidência
pointer: none-> visual neutro.pointer: coarse-> toque favorecido.pointer: fine-> cursor e precisão.
Variáveis-chave
pointerfont-sizecursor
Como explicar
Usei um estilo para ausência de apontador, outro para toque e outro para mouse ou touchpad. Assim a página evidencia o contexto de uso.
Erro comum
Usar o mesmo estilo nos três cenários e perder a distinção que a questão pede.
O que o enunciado pede
Dois botões com diferença visual conforme exista ou não a capacidade de hover.
Conceito cobrado
Separar capacidade de hover da precisão do apontador.
Estrutura dos dados
HTML mínimo: um wrapper com dois button.
<!-- index.html -->
<div class="buttons">
<button>Comprar</button>
<button>Saiba mais</button>
</div>
/* styles.css */
.buttons { display: flex; gap: 1rem; padding: 1rem; }
button { padding: 1rem 1.25rem; border: 0; border-radius: 10px; transition: .2s ease; }
@media (hover: none) {
button { background: #dee2e6; color: #111; }
}
@media (hover: hover) {
button { background: #343a40; color: #fff; }
button:hover { background: #0d6efd; transform: translateY(-2px); }
}Como pensar
Aqui o foco não é precisão de clique, e sim capacidade real de passar o mouse e ganhar um estado extra.
Como validar
Quando houver hover, o botão deve reagir ao passar do mouse. Quando não houver, o botão precisa continuar legível sem esse efeito.
Tabela de Evidência
hover: none-> botão estável.hover: hover-> estado visual ao passar o mouse.- Mesmo HTML -> só a condição muda.
Variáveis-chave
hover- estado
:hover transition
Como explicar
Quando há hover real, faz sentido adicionar resposta visual ao passar o mouse. Quando não há, o botão continua claro sem depender desse efeito.
Erro comum
Confundir hover com pointer e tratar as duas coisas como se fossem idênticas.
O que o enunciado pede
Uma página com header, main e footer, em light e dark.
Conceito cobrado
Preferência de tema do sistema aplicada à estrutura da página.
Estrutura dos dados
HTML mínimo: um wrapper .page com header, main e footer.
<!-- index.html -->
<div class="page">
<header>Header</header>
<main>Main</main>
<footer>Footer</footer>
</div>
/* styles.css */
:root { --bg: #ffffff; --fg: #111111; --panel: #f1f3f5; }
@media (prefers-color-scheme: dark) {
:root { --bg: #0b0d10; --fg: #f8f9fa; --panel: #1a1d22; }
}
body { margin: 0; background: var(--bg); color: var(--fg); }
.page { min-height: 100vh; display: grid; grid-template-rows: auto 1fr auto; }
header, main, footer { padding: 1rem; background: var(--panel); margin: .5rem; border-radius: 12px; }Como pensar
A estrutura continua igual. O que muda é só a paleta lida da preferência do usuário.
Como validar
Force light e dark no navegador e verifique se header, main e footer preservam legibilidade nos dois temas.
Tabela de Evidência
- Light -> painéis claros.
- Dark -> painéis escuros.
- Mesma grade vertical -> estrutura preservada.
Variáveis-chave
prefers-color-scheme--bg--panel
Como explicar
Usei prefers-color-scheme porque a questão pede detectar a preferência do usuário. O layout continua o mesmo; o que muda é a paleta.
Erro comum
Montar um segundo layout inteiro para dark em vez de trocar só os tokens.
O que o enunciado pede
Implementar apenas a versão mobile, em 414px, traduzindo o wireframe em blocos estruturais coerentes.
Conceito cobrado
Leitura de wireframe e organização hierárquica de layout mobile-only.
Estrutura dos dados
HTML mínimo completo: topo com marca e menu, hero, artigo com imagem, faixa de logos, CTA e rodapé em blocos empilhados.
<!-- index.html -->
<div class="mobile-page">
<header class="top">
<div class="brand">HOMCO</div>
<button class="menu-btn">☰</button>
</header>
<section class="hero-post">
<h1>Single Post</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</section>
<section class="post-card">
<img src="decor.jpg" alt="Imagem do artigo">
<h2>Tips Choice Best Agency for House Decoration</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<p>Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
</section>
<section class="logos">
<span>Logo 1</span><span>Logo 2</span><span>Logo 3</span><span>Logo 4</span>
</section>
<section class="cta">
<h3>Lets Change Your Own Home Interior Design Now</h3>
<a href="#">Contact Us</a>
</section>
<footer class="footer">
<div><h4>Information</h4><p>Texto institucional.</p></div>
<div><h4>Navigation</h4><p>Home<br>About<br>Services</p></div>
<div><h4>Contact Us</h4><p>hello@email.com</p></div>
</footer>
</div>
/* styles.css */
.mobile-page { width: 414px; max-width: 100%; background: white; }
.top, .logos { display: flex; justify-content: space-between; align-items: center; }
.top { padding: 1rem; }
.hero-post { padding: 2rem 1rem; }
.post-card, .cta, .footer { padding: 1rem; }
.post-card img { width: 100%; height: auto; margin-bottom: 1rem; }
.footer { display: grid; gap: 1rem; }Como pensar
O objetivo não é copiar pixel por pixel, e sim preservar a hierarquia do wireframe em uma largura fixa de 414px.
Como validar
Fixe o Device Toolbar em 414px. A página precisa funcionar inteira em uma coluna, sem depender de expansão para desktop.
Tabela de Evidência
- Topo -> marca + menu.
- Miolo -> hero, artigo, logos e CTA empilhados.
- Rodapé -> blocos finais ainda legíveis em 414px.
Variáveis-chave
width: 414px- blocos empilhados
- hierarquia do wireframe
Como explicar
Na transmutação mobile-only, o principal é preservar a hierarquia do desenho. Eu traduzi o wireframe em blocos empilhados e mantive a leitura clara em 414px.
Erro comum
Abrir breakpoints de desktop quando o exercício pede só a versão mobile.
Roteiro de estudo
01-02: picture vs img. 03-04: Flexbox a partir de protótipo. 05-06: Grid para centralização e áreas. 07-10: viewport e arquitetura de media queries. 11-15: contextos reais de adaptação. 16: tradução de wireframe.
Ao final, você deve conseguir dizer
Eu sei escolher entre picture e img, sei quando usar Flexbox e quando usar Grid, consigo montar media queries mobile-first, carregar CSS condicionalmente, adaptar interface por pointer, hover e prefers-color-scheme, e explicar o que muda quando altero a meta viewport.