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)
<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>
.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
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)
<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>
.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.
Conheça os livros do Maujor®
Visite o site dos livros do Maujor.
Os sites do Maujor estão hospedados na DialHost.