Wensity Layout
Layout é como uma página diz às pessoas o que importa e o que pertence junto, antes que leiam uma palavra. Um bom layout vem de três hábitos: uma escala de espaçamento fixa, agrupamento por distância e um sistema de alinhamento. Este skill configura os três e cobre estrutura responsiva.
Se o projeto já possui uma escala de espaçamento e larguras de container, use-os.
1. A escala de espaçamento
Use uma base de 4px. Cada margem, padding e gap vem desta lista:
| Token | px | Uso típico |
|---|---|---|
| 1 | 4 | ícone ao rótulo, gaps inline apertados |
| 2 | 8 | dentro de um controle, entre um rótulo e seu input |
| 3 | 12 | entre itens em uma lista densa, padding y de botão |
| 4 | 16 | padding de card (compacto), gap entre controles relacionados, gutter de página mobile |
| 5 | 20 | padding x de botão (grande) |
| 6 | 24 | padding de card, gap entre campos de formulário |
| 8 | 32 | entre grupos dentro de uma seção |
| 10 | 40 | entre um título de seção e seu conteúdo (grande) |
| 12 | 48 | padding de seção em mobile |
| 16 | 64 | entre seções em um app, padding de seção em tablet |
| 20 | 80 | |
| 24 | 96 | padding de seção em páginas de marketing desktop |
| 32 | 128 | padding de hero, o espaço em torno de uma grande declaração |
A escala padrão do Tailwind já segue uma base de 4px (p-4 é 16px), então use
seus passos e não invente p-[13px]. Valores ímpares são permitidos apenas para
correções ópticas que você verificou na renderização (um ícone que parece desalinhado em 1px).
2. Agrupe por distância
A regra de layout mais importante: o espaço dentro de um grupo é menor que o espaço entre grupos. Um rótulo fica a 8px de seu input; o próximo campo fica a 24px de distância. O título de um card fica a 8px acima de seu texto; o próximo card fica a 24px de distância. Quando o espaçamento interno e externo são iguais, tudo flutua soltamente e nada é lido como um grupo.
- Busque uma proporção de cerca de 1 para 2 ou 1 para 3 entre gaps internos e externos.
- Mais espaço acima de um título do que abaixo dele. O título pertence ao conteúdo que vem depois. Típico: 48px acima de um título de seção, 16px abaixo.
- Espaçamento antes de caixas. Agrupe com distância primeiro. Adicione uma borda, divisor ou fundo apenas quando a distância não é suficiente (tabelas densas, barras de ferramentas, conteúdo em fundos ocupados). Uma caixa em torno de cada grupo torna a página pesada.
- Use
gappara irmãos (flex gap-4,grid gap-6) em vez de margens em filhos. Mantém o espaçamento em um só lugar e evita margens extras nas extremidades de uma lista.
3. Ritmo, não uniformidade
Uma página onde cada seção tem 96px de padding, um título centralizado e uma grade de três itens não tem ritmo. Varie a densidade propositalmente:
- Alterne seções densas (grades de recursos, tabelas, logotipos) com seções abertas (uma declaração, uma imagem grande).
- Deixe que seções importantes ocupem mais espaço. Espaço é como você gasta atenção.
- Repita um layout apenas quando o conteúdo é realmente o mesmo tipo de coisa.
4. Alinhamento
- Uma borda de início. Títulos, parágrafos, botões e imagens em uma seção compartilham a mesma linha inicial. A maioria das reclamações de "algo parece errado" é duas bordas a alguns pixels de distância.
- Alinhe ao início por padrão (
text-align: start, que é esquerda em inglês e direita em árabe ou hebraico). Centralize apenas conteúdo curto e independente: um título de hero, um bloco de CTA único, um estado vazio. Formulários, tabelas, listas e texto longo alinham ao início. - Alinhe números ao final em tabelas e colunas de estatísticas.
- Alinhe ao texto, não às caixas. Um ícone ao lado de um rótulo alinha com a
altura da caixa alta ou centro do rótulo, não com o topo da linha. Em linhas flex,
items-centerpara linhas únicas;items-startmais uma margem superior pequena no ícone para texto multi-linha. - Ajustes ópticos: ícones de play, setas e formas arredondadas parecem descentralizados quando centralizados matematicamente. Ajuste de 1 a 2px depois de ver.
5. Containers e larguras
| Container | Largura máxima | Uso |
|---|---|---|
| Prosa | 65ch (cerca de 640 a 720px) | artigos, documentação, parágrafos longos |
| Estreito | 560 a 640px | formulários, login, tarefas focadas, uma declaração hero centralizada |
| Conteúdo | 1120 a 1280px | a maioria das seções de marketing e páginas de app |
| Largo | 1440 a 1600px | dashboards, galerias, editores |
| Sangria total | 100% | fundos, imagens, fotos de produto que devem tocar as bordas |
- Gutter da página: 16px em telefones, 24px em tablets, 32 a 48px em desktop. Mantenha consistente: um valor de gutter por breakpoint para todo o site.
- Separe fundo da largura do conteúdo. O fundo de uma seção pode ocupar toda a largura enquanto seu conteúdo permanece no container de conteúdo.
- Não deixe o texto ocupar toda a largura em telas largas. Imagens e grids podem crescer; parágrafos não.
6. Grids
- 12 colunas para layouts de marketing dá metades, terços, quartos e divisões assimétricas (7 e 5, 8 e 4). Divisões assimétricas parecem mais projetadas do que 6 e 6.
- Grids de preenchimento automático para cards para que o número de colunas siga o espaço:
.cards { display: grid; gap: 24px; grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr)); }
O min(100%, 280px) evita transbordamento em telas mais estreitas que 280px.
auto-fill mantém a largura do card estável quando há apenas um ou dois cards;
auto-fit estica os poucos cards para preencher a linha. Escolha propositalmente.
- Deixe trilhas flexíveis encolherem. Filhos de grid e flex se recusam a encolher
abaixo de seu conteúdo por padrão, que é o motivo pelo qual texto longo ou uma tabela larga
transborda em um dashboard. Use
minmax(0, 1fr)para trilhas flexíveis emin-width: 0(Tailwindmin-w-0) em filhos flex que contêm texto:
.app-shell { display: grid; grid-template-columns: 16rem minmax(0, 1fr); }
.row > .text { min-width: 0; }
- Alturas iguais apenas para conteúdo igual. Cards em uma linha se esticam até o mais alto por padrão em grid. Bom para um conjunto de planos; errado quando um card é claramente o destacado.
- Grids Bento: varie tamanhos dos tiles por importância, mantenha um valor de gap, e dê a cada tile um pedaço real de conteúdo. Tiles decorativos vazios parecem um template.
- Use subgrid (
grid-template-rows: subgrid) quando cards em uma linha precisam que seus títulos, corpos e botões se alinhem entre si.
7. Estrutura responsiva
Projete mobile primeiro, depois adicione estrutura conforme o espaço cresce.
- Breakpoints seguem o conteúdo, não dispositivos. Adicione um onde o layout
começa a parecer errado. Os padrões do Tailwind
sm 640,md 768,lg 1024,xl 1280são bons padrões. - Reestruture, não apenas encolha. Em mobile, uma grade de três colunas de recursos se torna uma coluna, texto e imagem lado a lado empilham com a imagem depois (ou primeiro se ela carrega a mensagem), uma tabela se torna uma lista de cards ou rola horizontalmente dentro de seu próprio container, uma barra lateral se torna um drawer.
- Container queries para componentes que aparecem em diferentes larguras (um card em uma barra lateral e em uma coluna principal):
.card-wrap { container-type: inline-size; }
@container (min-width: 480px) { .card { grid-template-columns: 160px 1fr; } }
No Tailwind v4: @container no pai e @md:grid-cols-2 no filho.
- Escalone o espaçamento com a tela. Padding da seção: 48px mobile, 64px tablet, 96px desktop. Gaps podem passar de 16 para 24 para 32.
- Altura da viewport: use
min-h-dvh(ou100dvh), nãoh-screen(100vh), para layouts de altura total.100vhé mais alto que a área visível em navegadores mobile com barra de ferramentas, então o conteúdo fica escondido. - Áreas seguras em telefones com entalhes:
padding-bottom: env(safe-area-inset-bottom)em barras inferiores fixas, comviewport-fit=coverna meta tag viewport. - Idiomas da direita para a esquerda: use propriedades lógicas (
margin-inline-start,padding-inline,inset-inline-end; no Tailwindms-*,pe-*,start-*) em vez de esquerda e direita, e teste comdir="rtl". Espelhe ícones direcionais (setas para trás, chevrons), não logotipos ou todos os ícones. - Nunca haja rolagem horizontal na página. Verifique em 320px. As causas comuns são uma
largura fixa, uma palavra longa ou URL, um elemento
w-screen(que inclui a largura da barra de rolagem), ou uma margem negativa.
8. Tabelas
- Linha de cabeçalho no papel de rótulo, sticky (
position: sticky; top: 0) quando a tabela rola, em uma superfície matizada ou com uma borda inferior mais forte. - Altura da linha por densidade: 36px compacta, 44px padrão, 52px confortável. Ofereça um alternador quando os usuários diferirem.
- Linhas separadas por divisores finos ou por matização zebrada, não ambos.
- Números alinhados ao final com
tabular-nums; texto alinhado ao início; status e ações nas últimas colunas. - Tabelas largas em mobile: role horizontalmente dentro de seu próprio container
(
overflow-x: auto) com a primeira coluna sticky, ou mude para um card empilhado por linha. Nunca deixe uma tabela empurrar a página para o lado. - Estados vazio, carregando e de erro residem dentro do quadro da tabela, mantendo o cabeçalho para que o usuário saiba o que aparecerá.
9. Densidade
Combine a densidade com a frequência com que a tela é usada:
- Marketing e onboarding: aberta. Poucos itens por tela, espaço generoso, tipo grande.
- Telas de aplicativos de uso diário: compacta. Linhas de 36 a 44px, gaps de 8 a 12px, texto de 14px. Pessoas que usam uma tela todos os dias querem ver mais de uma vez.
- Tabelas e ferramentas de dados: densas, com um alternador de densidade se os usuários diferirem.
- Não misture densidades dentro de um único painel.
10. Alvos de toque e áreas de clique
- Alvo de 44 por 44px para qualquer coisa tocável em telas de toque, mesmo que o ícone visível seja 16px. (WCAG 2.2 AA exige pelo menos 24 por 24px; 44 é o tamanho confortável.) Aumente a área de clique com padding, ou com um pseudo-elemento invisível centralizado no controle para que o layout não mude:
.icon-btn { position: relative; }
.icon-btn::before {
content: ""; position: absolute; left: 50%; top: 50%;
width: max(100%, 44px); height: max(100%, 44px);
transform: translate(-50%, -50%);
}
- Pelo menos 8px entre alvos de toque separados para que um polegar não atinja dois.
11. Camadas
Mantenha uma escala z-index pequena e use apenas estes valores:
:root { --z-dropdown: 10; --z-sticky: 20; --z-overlay: 30; --z-modal: 40; --z-toast: 50; --z-tooltip: 60; }
<dialog> nativo aberto com showModal() e elementos com o atributo popover
renderizam na camada superior do navegador, acima de qualquer z-index, então
eles não precisam de nenhum. z-index: 9999 significa que o empilhamento não é compreendido. Corrija o contexto
de empilhamento (geralmente um transform, filter ou isolation perdido em um pai)
em vez de aumentar o número.
12. Elementos sticky e fixed
- Cabeçalhos sticky: mantenha-os curtos (56 a 64px), e dê a eles um fundo (sólido ou desfocado) apenas quando a página rolar sob eles, para que o topo da página permaneça limpo.
- Adicione
scroll-margin-topigual à altura do cabeçalho em títulos ancorados para que links internos não caiam sob o cabeçalho. - Barras inferiores fixas em mobile precisam do padding de área segura acima e não devem cobrir o último conteúdo na página; adicione padding na parte inferior da página pela altura da barra.
13. Verifique antes de terminar
- Cada valor de espaçamento está na escala de 4px.
- O espaço dentro dos grupos é claramente menor que o espaço entre eles.
- Mais espaço acima dos títulos do que abaixo.
- Uma borda de início por seção; números alinhados ao final em tabelas.
- Trilhas flexíveis usam
minmax(0, 1fr); filhos de texto podem encolher. - Parágrafos limitados a cerca de 65ch, mesmo em telas largas.
- Layout se reestrutura em mobile em vez de apenas encolher.
- Sem rolagem horizontal em 320px; seções de altura total usam
dvh. - Alvos de toque de pelo menos 44px (nunca abaixo de 24px).
- Valores de z-index vêm da escala.
- Teste do olho semicerrado: a coisa mais importante e os grupos estão claros com os detalhes desfocados.