Grid layout

Exemplo Prático: Estrutura macro de um portal

Este primeiro exemplo aborda os conceitos fundamentais do CSS Grid Layout, a ferramenta mais poderosa e versátil para a criação de estruturas bidimensionais na web moderna. Diferente de métodos anteriores, o Grid permite o controle simultâneo de linhas e colunas, estabelecendo uma malha lógica onde os elementos podem ser posicionados com precisão cirúrgica.

A finalidade deste exemplo é capacitar o desenvolvedor a estruturar layouts macro, como portais com colunas laterais, utilizando áreas nomeadas e compreendendo a diferença crucial entre o dimensionamento ditado pelo conteúdo (intrínseco) e o imposto pelo autor (extrínseco).

Fundamento teórico

O CSS Grid Layout baseia-se no conceito de um "container" (pai) e "itens" (filhos). Ao definir display: grid, o navegador cria um contexto de formatação onde o espaço é dividido por linhas de grade (grid lines), formando trilhas (tracks), células e áreas.

Um dos pilares do Grid moderno é o sistema de dimensionamento. O dimensionamento extrínseco ocorre quando definimos tamanhos fixos ou percentuais, por exemplo: width: 500px.
Já o dimensionamento intrínseco utiliza as palavras-chave min-content (o menor tamanho que o conteúdo pode assumir sem transbordar), max-content (o tamanho ideal do conteúdo sem quebras de linha) e fit-content (um equilíbrio que respeita um limite máximo, mas encolhe conforme o conteúdo).

Para layouts responsivos, a função minmax(min, max) é indispensável, pois permite que uma coluna ou linha tenha uma base mínima de segurança, mas cresça para ocupar o espaço disponível. Complementarmente, as unidades de fração (fr) distribuem o espaço livre de forma proporcional, eliminando cálculos matemáticos complexos de porcentagem.

Aplicação prática

Vamos desenvolver a estrutura macro de um portal clássico: topo, barra lateral, conteúdo principal e rodapé. Utilizaremos a técnica de áreas nomeadas (grid-template-areas), que oferece a sintaxe mais legível e fácil de manter para layouts de grande escala.

Nota: Essa aplicação está disponível para consulta/download em 🔗 App Portal (link abre em nova janela)

HTML
<div class="container-portal">
  <header class="topo">Topo do Portal</header>
  <aside class="lateral">Barra Lateral</aside>
  <main class="conteúdo">Conteúdo Principal</main>
  <footer class="rodapé">Rodapé</footer>
</div>
CSS
.container-portal {
  display: grid;
  grid-template-columns: minmax(200px, 1fr) 3fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
  "header header"
  "sidebar main"
  "footer footer";
  min-height: 100vh;
  gap: 20px;
  padding: 20px;
}

.topo { grid-area: header; }
.lateral { grid-area: sidebar; }
.conteúdo { grid-area: main; }
.rodapé { grid-area: footer; }

/* Ajuste para telas pequenas */
@media (max-width: 600px) {
.container-portal {
  grid-template-columns: 1fr;
  grid-template-areas:
  "header"
  "main"
  "sidebar"
  "footer";
  gap: 12px;
  padding: 12px;
  }
}

CSS comentado

.container-portal { display: grid; }

Define o contexto de grid bidimensional e a estrutura macro da página. Ao aplicar display: grid, os filhos diretos deste container passam a ser posicionados automaticamente nas áreas definidas


grid-template-columns: minmax(200px, 1fr) 3fr;

Define duas colunas:
A primeira (sidebar) tem mínimo de 200px e máximo de 1 fração (1fr)
A segunda (main) ocupa 3 frações do espaço restante
O uso de minmax() garante que a sidebar nunca encolha abaixo de 200px, mesmo em viewports estreitas. Isso é dimensionamento intrínseco: o tamanho respeita limites mínimos e máximos em vez de ser fixo


grid-template-rows: auto 1fr auto;

Define três linhas:
auto: a linha do topo cresce conforme o conteúdo (intrínseco) 1fr: o main ocupa o espaço vertical restante auto: o rodapé cresce conforme o conteúdo (intrínseco) A combinação de auto com 1fr faz com que o main absorva o espaço livre vertical, mantendo header e footer compactos


grid-template-areas:
  "header header"
  "sidebar main"
  "footer footer";

Mapeia cada elemento HTML para uma área nomeada A sintaxe visual facilita a compreensão do layout: Primeira linha: "header header" o topo ocupa as duas colunas Segunda linha: "sidebar main" a lateral e conteúdo lado a lado Terceira linha: "footer footer" o rodapé ocupa as duas colunas Cada string representa uma linha do grid; cada nome representa uma célula. Nomes repetidos na mesma linha indicam que a área ocupa múltiplas colunas


min-height: 100vh;

Garante que o container ocupe no mínimo a altura total da viewport. Sem isso, se o conteúdo for pequeno, o rodapé pode flutuar no meio da tela. Combinado com >grid-template-rows: auto 1fr auto>, o rodapé fica sempre na parte inferior da viewport quando há pouco conteúdo


gap: 20px;

Define o espaçamento entre as trilhas (linhas e colunas). Sem gap, os itens ficariam colados uns nos outros. O gap é aplicado apenas entre trilhas, nunca nas bordas externas do container, o que mantém o alinhamento consistente


padding: 20px;

Espaçamento interno do container para evitar que o conteúdo fique colado nas bordas da viewport. Complementa o gap criando respiro visual nas margens externas do grid


.topo { grid-area: header; }
.lateral { grid-area: sidebar; }
.conteudo { grid-area: main; }
.rodape { grid-area: footer; }

Cada filho direto do container deve ter grid-area igual a um dos nomes definidos em grid-template-areas. A propriedade grid-area, quando recebe um único nome, posiciona o elemento na área correspondente, substituindo a necessidade de informar manualmente line-start/column-start/line-end/column-end


Ajuste responsivo com media query
Quando a viewport for menor ou igual a 600px de largura, o layout de duas colunas se torna inviável. A media query redefine o grid para coluna única, empilhando todas as áreas verticalmente. Isso demonstra como o grid é adaptável: apenas as propriedades de template são redefinidas, sem precisar alterar o HTML ou a associação de áreas

grid-template-columns: 1fr;

Muda para uma única coluna que ocupa 1 fração da largura. Com uma única coluna, todos os itens se empilham naturalmente na direção em coluna (block) do grid


grid-template-areas:
  "header"
  "main"
  "sidebar"
  "footer";

A ordem das áreas na sintaxe determina a ordem visual header, main, sidebar, footer.
A ordem de tabulação e a leitura por leitores de tela seguem a ordem do DOM, não a ordem visual do grid-template-areas. O HTML deve estar na sequência lógica correta independentemente da disposição visual. Por isso, no mobile, main aparece antes de sidebar para priorizar o conteúdo principal


gap: 12px;

Reduz o gap no mobile para aproveitar melhor o espaço limitado da viewport estreita


padding: 12px;

Reduz o padding externo no mobile para maximizar a área útil de conteúdo em telas pequenas

Análise de acessibilidade

Ao utilizar grid-template-areas ou a propriedade order, é possível mover elementos visualmente para qualquer lugar da tela. No entanto, a ordem de tabulação (teclado) e a leitura por tecnologias assistivas seguem estritamente a ordem do código HTML (DOM). Sempre mantenha o HTML em uma sequência lógica de leitura por exemplo: Topo > Conteúdo > Lateral > Rodapé e use o CSS apenas para o posicionamento visual. Nunca use o Grid para compensar um HTML mal estruturado semanticamente.

Desafio técnico

Modifique o código acima para que a barra lateral utilize fit-content(250px). Observe como o layout se comporta quando o texto da lateral é muito curto e quando ele atinge o limite de 250px. Tente também adicionar uma segunda barra lateral à direita e atualizar a propriedade grid-template-areas para acomodá-la.

Conclusão

O CSS Grid Layout transforma a criação de interfaces macro em uma tarefa lógica e descritiva. Compreender a diferença entre dimensionamento intrínseco e extrínseco é o que separa um layout rígido de um layout resiliente e moderno. Através de áreas nomeadas, o código torna-se uma representação visual da própria estrutura da página.

Notas de compatibilidade

O CSS Grid básico tem suporte universal, 98%+ dos navegadores. Funções como minmax() e unidades fr são amplamente estáveis. Para navegadores extremamente antigos (legados), a estratégia de progressive enhancement consiste em fornecer um layout simplificado em coluna única (fluxo normal) e aplicar o Grid dentro de um bloco @supports (display: grid).

Recurso Chrome Firefox Safari Edge
CSS Grid (básico) 57+ 52+ 10.1+ 16+
minmax() 57+ 52+ 10.1+ 16+
grid-template-areas 57+ 52+ 10.1+ 16+

Resumindo

Neste tutorial, vimos como o CSS Grid organiza layouts macro através de containers e áreas nomeadas. Aprendemos a importância do dimensionamento intrínseco para a resiliência do design e como garantir que a acessibilidade não seja prejudicada pelo reposicionamento visual dos elementos.

Exemplo Prático: Grade de cards

Neste segundo exemplo de aplicação prática exploraremos a criação de uma grade de cards com comportamento resiliente. O foco recai sobre como o CSS Grid lida com a distribuição de espaço quando os itens possuem volumes de conteúdo distintos, utilizando unidades flexíveis e funções de repetição inteligente.

A finalidade deste exemplo é demonstrar a versatilidade das trilhas de grade no gerenciamento de áreas de conteúdo que precisam manter harmonia visual, mesmo sem a definição de alturas fixas (dimensionamento extrínseco), priorizando a fluidez do design.

Fundamento teórico

A base técnica deste exemplo reside na função repeat() combinada com as palavras-chave auto-fill ou auto-fit. Enquanto o dimensionamento extrínseco (como width: 300px) cria estruturas rígidas, o uso de grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)) permite que o navegador calcule quantas colunas cabem no espaço disponível, garantindo que cada uma tenha no mínimo 220px e expanda proporcionalmente para preencher o restante. Essa abordagem elimina a necessidade de media queries para ajustes de quebra de linha.

O alinhamento vertical dos elementos dentro de cada card, por sua vez, é resolvido com display: flex e flex-direction: column no card, combinado com margin-top: auto no último filho (.card > :last-child). Diferentemente do flex-grow: 1 aplicado a um elemento intermediário, que cria dependência de uma classe específica e quebra se a estrutura do card mudar, o margin-top: auto no último filho empurra esse elemento para o fundo do card de forma genérica e desacoplada. O seletor :last-child garante que qualquer tag (botão, link, lista) ocupe a posição inferior, independentemente da quantidade ou do tipo de elementos anteriores.

Aplicação prática

Desenvolveremos uma Grade de Cards onde o alinhamento vertical deve ser preservado mesmo que um card tenha mais texto que o outro.

Nota: Essa aplicação está disponível para consulta/download em 🔗 Grade de cards (link abre em nova janela)

HTML
<main class="grid">
<article class="card">
  <h2>Card 1</h2>
  <p>Conteúdo curto.</p>
  <button>Ação</button>
</article>

<article class="card">
  <h2>Card 2</h2>
  <p>Conteúdo um pouco mais longo, com mais de uma frase para demonstrar diferença de altura entre os cards da grade.</p>
  <p>Outro parágrafo adicional.</p>
  <a href="#">Ver mais</a>
</article>

<article class="card">
  <h2>Card 3</h2>
  <p>Conteúdo médio com uma lista de links como último elemento.</p>
  <ul>
    <li><a href="#">Link 1</a></li>
    <li><a href="#">Link 2</a></li>
    <li><a href="#">Link 3</a></li>
  </ul>
</article>
  </main>
CSS
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 16px;
  }

  .card {
  display: flex;
  flex-direction: column;
  }

  .card > :last-child {
  margin-top: auto;
  }

Análise de acessibilidade:

Ao estruturar listas de itens como cards, utilize elementos semânticos como <section>, <article> ou listas <ul>/<li>. O CSS Grid não altera a semântica, mas a ordem visual deve respeitar a hierarquia de importância. Evite usar grid-column ou grid-row para saltar a ordem natural de leitura dos cards, pois usuários de teclado percorrerão os elementos na sequência em que aparecem no HTML.

Desafio técnico

Tente alterar a propriedade grid-template-columns para usar auto-fill em vez de auto-fit. Adicione apenas dois cards e observe a diferença: com auto-fit, os dois cards se expandirão para ocupar toda a largura; com auto-fill, o navegador reservará espaço para colunas vazias se houver largura disponível.

Conclusão

A utilização de funções de repetição e unidades de fração (fr) permite criar layouts que se adaptam organicamente ao conteúdo e ao dispositivo. O Grid Layout elimina a necessidade de hacks para equalização de alturas, proporcionando um código limpo e de fácil manutenção.

Notas de compatibilidade: As funções repeat(), minmax() e as palavras-chave auto-fill/auto-fit possuem suporte robusto em todos os navegadores modernos (Evergreen browsers).

Recurso

Browser repeat() auto-fill / auto-fit
Chrome 57+ 57+
Firefox 52+ 52+
Safari 10.1+ 10.1+
Edge 16+ 16+

Resumindo

Este exemplo demonstrou como o CSS Grid resolve problemas de alinhamento e responsividade de forma nativa. Vimos que a combinação de dimensionamento intrínseco com trilhas flexíveis resulta em componentes robustos que dispensam o uso excessivo de media queries.

Compartilhe essa matéria com seus amigos

logo twitter logo facebook logo linkedin

Conheça os livros do Maujor®

Visite o site dos livros do Maujor.

Os sites do Maujor estão hospedados na DialHost.