Capítulo 43
Módulos e layout composto
6 min de leitura 1.159 palavras 2 gravuras
Este capítulo junta as peças da Oficina Costeira: card, botão, lista, cabeçalho e rodapé viram módulos. A Oficina Costeira é um coletivo fictício de design em João Pessoa. Este volume tem 52 capítulos. Esta é a 43.
O exemplo está em exemplos/43-modulos-layout/. Grade e tipo já existem. Agora você compõe a página com blocos reutilizáveis e um wireframe que já é HTML. Ciclo: ler, copiar, mudar uma coisa, prever, recarregar, conferir.
O que você vai aprender
- Reconhecer um módulo: HTML + CSS que servem em mais de um lugar.
- Montar card, botão e grupo de lista sem copiar regras.
- Compor a home com cabeçalho, destaque, grade e rodapé.
- Usar um wireframe clicável em vez de um desenho morto.
- Evitar classe que descreve a cor do dia.
- Manter acessibilidade quando a peça se repete.
Módulo é peça com contrato
Um módulo é um pedaço que você reconhece de longe: o card de projeto, o botão de ação, o menu. Ele tem HTML estável, CSS próprio e um jeito de entrar na página sem quebrar o vizinho.
Pense no card da Oficina Costeira. O contrato é simples: um article, um título, um parágrafo. Pode ganhar imagem depois. Não pode exigir que o pai seja a home.
<article class="card">
<h2>Farol da Restinga</h2>
<p>Identidade fictícia para um festival de fotografia.</p>
</article>
.card {
background: #fff;
padding: 1.25rem;
border: 1px solid #d9d3c7;
}
.card h2 {
margin-top: 0;
font-size: 1.15rem;
}
Se projetos e a home usam o mesmo card, o CSS vive uma vez em main.css. Mudou o padding, mudou nos dois lugares. Isso é o oposto de copiar e colar um bloco por página.
Mude só o padding para 2rem. Preveja cards mais folgados na home e em projetos. Recarregue as duas páginas. Confira. Se só uma mudou, você editou o HTML local com style, não o módulo.
Erro comum: .card-home e .card-projetos com as mesmas declarações. Extraia. Um .card basta.
Botão, lista e grupo
O botão da Oficina Costeira não envia nada para a rede. Mesmo assim ele precisa parecer e se comportar como botão: foco visível, texto que diz a ação, type="button" quando não envia formulário.
<p>
<button type="button">Ver agenda fictícia</button>
</p>
button {
font: inherit;
color: #fff;
background: #0b4f6c;
border: 0;
padding: 0.5rem 1rem;
}
button:focus-visible {
outline: 3px solid #c45c26;
outline-offset: 3px;
}
Grupo de lista é uma lista sem bolinha, usada em menu ou em equipe:
<ul class="lista-grupo">
<li>Lina Vasconcelos — direção de arte (personagem fictícia).</li>
<li>Rui Pedrosa — conteúdo e acessibilidade (personagem fictício).</li>
<li>Nara Queiroz — desenvolvimento de páginas (personagem fictícia).</li>
</ul>
.lista-grupo {
list-style: none;
padding: 0;
}
.lista-grupo li + li {
margin-top: 0.5rem;
padding-top: 0.5rem;
border-top: 1px solid #d9d3c7;
}
Mude só o texto do botão para Abrir agenda. Preveja o rótulo novo. Recarregue. Confira. Não troque button por div clicável.
Erro comum: usar a com classe de botão para uma ação que não leva a outro documento. Link vai a uma URL. Botão faz uma ação na página. Formulário usa button type="submit", ainda sem envio real.
Compor a página
Layout composto é a soma: cabeçalho + miolo + rodapé. O miolo da home é destaque + grade de cards. Cada região é um módulo. A página só empilha.
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Início — Oficina Costeira</title>
<link rel="stylesheet" href="assets/stylesheets/main.css">
</head>
<body>
<a class="skip" href="#conteudo">Pular para o conteúdo</a>
<header class="site-header">
<p><a class="brand" href="index.html">Oficina Costeira</a></p>
<nav aria-label="Principal">
<ul class="menu">
<li><a href="index.html" aria-current="page">Início</a></li>
<li><a href="projetos.html">Projetos</a></li>
</ul>
</nav>
</header>
<main id="conteudo" class="wrap">
<section class="hero">
<h1>Oficina Costeira</h1>
<p>Coletivo fictício de design em João Pessoa.</p>
</section>
<div class="cards">
<article class="card"><h2>Identidade</h2><p>Marcas perto do mar.</p></article>
<article class="card"><h2>Publicação</h2><p>Sites estáticos de estudo.</p></article>
</div>
</main>
<footer class="site-footer">
<p>Oficina Costeira — João Pessoa. Conteúdo fictício.</p>
</footer>
</body>
</html>
O cabeçalho não sabe quantos cards existem. O card não sabe se está na home. Essa ignorância é boa: você troca a ordem sem reescrever o CSS de cada peça.
Mude só a ordem: coloque os cards acima do .hero. Preveja a grade primeiro, o título depois. Recarregue. Confira. Depois devolva o destaque no topo. A composição é HTML. O CSS dos módulos permanece.
Erro comum: um seletor do tipo header div nav ul li a. Quando o HTML do módulo muda, o CSS quebra. Selecione .menu a.

Wireframe que já abre no navegador
Wireframe interativo, neste volume, não é um poster. É HTML com links de verdade, pouco CSS e o mesmo skip-link. Você clica de Início para Projetos e volta. O mapa do site se prova antes da pintura fina.
Comece cinza, se quiser:
.wire .card {
background: #eee;
border: 1px dashed #666;
}
.wire .site-header,
.wire .site-footer {
background: #ccc;
color: #14222b;
}
No body da página de rascunho, acrescente a classe wire. Os módulos continuam sendo módulos. Só o visual fica de diagrama.
Quando o clique já funciona, tire wire e devolva as cores da marca. Não desenhe o menu de novo no editor de imagem e “depois passa para código”. O código já é o desenho.
Mude só o destino do link Projetos para equipe.html. Preveja: o menu leva à equipe. Recarregue. Clique. Confira. Corrija o href. O wireframe serve para achar esse erro cedo.
Erro comum: prototipar só em ferramenta gráfica e descobrir no HTML que o menu não cabe. Prototipe na pasta do exemplo.
Nomeie o papel, não a tinta
Classe boa descreve função: .card, .menu, .hero, .skip. Classe frágil descreve o visual do dia: .azul, .grande, .esquerda.
Quando a marca da Oficina Costeira mudar de #0b4f6c para outro azul, você troca a variável ou a regra do cabeçalho. Não percorre o HTML caçando .azul-marinho.
Utilitários (text-center, bold) existem. Use pouco. Se cada frase ganha três classes de força bruta, o módulo desapareceu.
Checklist do módulo:
- HTML semântico;
- uma classe principal;
- CSS no
main.css; - funciona em mais de uma página;
- foco visível;
aria-currentsó no link da página atual.
Mude só uma classe no HTML de um card para azul. Preveja: nada muda, porque o CSS não conhece .azul. Recarregue. Confira. Volte para .card.
Erro comum: divite — trocar article e h2 por div porque “o CSS já deixa bonito”. O módulo perde significado para leitor de tela e para você daqui a um mês.
Juntar grade, tipo e módulo
Os três volumes desta série se encontram agora. A grade (.cards) é o recipiente. A escala tipográfica manda no h1 e no h2. O card é o módulo. Nenhum deles substitui o outro.
Abra exemplos/43-modulos-layout/index.html. Percorra com Tab. A ordem deve ser skip-link, marca, menu, conteúdo, rodapé. Estreite a janela: uma coluna. Alargue: a grade dos cards abre.
Não publique. Os nomes da equipe são fictícios. O formulário de contato, se você abrir, não envia dado.
python -m http.server 8769 --bind 127.0.0.1 --directory curso
Encerre com Ctrl+C. Não use 0.0.0.0.
Ferramentas que geram pacotes de módulo existem. Você não precisa delas. Se um dia colar um pacote, leia cada classe antes de deixar no projeto.

Atividades
- O que o card precisa saber sobre a home para funcionar?
- Quando usar
buttone quando usarano módulo de ação? - Por que um wireframe em HTML é mais útil aqui do que um cartaz estático?
- Dê um exemplo de nome de classe frágil e um de nome estável.
- Se o CSS do
.cardmudar, em quantas páginas da Oficina Costeira o visual deve acompanhar?
Respostas comentadas
- Nada. Ele só precisa do próprio HTML e da classe
.card. O pai cuida da grade. aquando há URL de destino.buttonquando a ação é na página. Envio de formulário fictício usasubmit, ainda sem servidor de verdade.- Porque os links já se testam. Você descobre menu quebrado e ordem de foco antes de pintar.
- Frágil:
.azul-bonito. Estável:.cardou.menu. - Em todas as que usam
.card(home e as internas que repetirem o módulo), porque o CSS é um só.
Referências
O arquivo completo
Referência do exemplo 43-modulos-layout, reproduzida aqui para que você possa conferir sem sair da página.
assets/javascript/simulacao.js
const form=document.querySelector("#simulacao");if(form){form.querySelector("button[type=submit]").disabled=false;form.addEventListener("submit",event=>{event.preventDefault();document.querySelector("#retorno").textContent="Simulação concluída. Nada foi enviado ou guardado.";});}