Capítulo 9 — Layout com Grid¶
Vídeo curto explicativo (link será adicionado posteriormente)
9.1 — O que é CSS Grid e quando usar¶
Vídeo curto explicativo (link será adicionado posteriormente)
O CSS Grid Layout é o sistema de layout bidimensional nativo do CSS — projetado especificamente para organizar elementos em linhas e colunas simultaneamente. Enquanto o Flexbox opera em uma única dimensão (uma linha ou uma coluna por vez), o Grid permite posicionar elementos em uma grade com controle preciso sobre ambos os eixos ao mesmo tempo.
Publicado como recomendação pelo W3C em 2017 e com suporte amplo em todos os navegadores modernos desde então, o CSS Grid representa a ferramenta mais poderosa já disponibilizada nativamente pelo CSS para criação de layouts — eliminando a necessidade dos sistemas de grid baseados em frameworks como Bootstrap para a maioria dos casos de uso.
9.1.1 — O problema que o Grid resolve¶
Antes do CSS Grid, criar layouts de duas dimensões — como a estrutura clássica de uma página web com cabeçalho, conteúdo principal, sidebar e rodapé — exigia combinações complexas de floats, posicionamento absoluto ou frameworks externos:
/* Era pré-Grid: layout com float */
.header { width: 100%; }
.main { float: left; width: 70%; }
.sidebar { float: right; width: 28%; margin-left: 2%; }
.footer { clear: both; width: 100%; }
/* Problemas: clearfix necessário, altura igual entre colunas impossível,
reordenação para mobile requer JavaScript ou marcação adicional */
Com CSS Grid, o mesmo layout é declarado de forma clara, semântica e manutenível:
.pagina {
display: grid;
grid-template-columns: 1fr 300px;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"main sidebar"
"footer footer";
min-height: 100vh;
}
9.1.2 — Conceito de grid container, grid items, linhas, colunas e células¶
O Grid opera em dois níveis, assim como o Flexbox:
- Grid container: o elemento ao qual
display: gridé aplicado. Define a estrutura da grade. - Grid items: os filhos diretos do grid container. São posicionados nas células da grade.
A grade em si é composta por:
- Colunas (columns): divisões verticais da grade
- Linhas (rows): divisões horizontais da grade
- Células (cells): a intersecção de uma linha com uma coluna — a unidade mínima da grade
- Áreas (areas): agrupamento retangular de uma ou mais células adjacentes
9.1.3 — Terminologia: grid lines, tracks, areas e gaps¶
O CSS Grid possui uma terminologia precisa que é essencial dominar para interpretar a especificação e a documentação:
col 1 col 2 col 3
| | | |
linha 1| [1,1] | [1,2] | [1,3] |
| | | |
linha 2| [2,1] | [2,2] | [2,3] |
| | | |
linha 3| [3,1] | [3,2] | [3,3] |
| | | |
Grid lines (linhas de grade): as linhas divisórias numeradas
→ colunas: 1, 2, 3, 4 (n colunas = n+1 linhas verticais)
→ linhas: 1, 2, 3, 4 (n linhas = n+1 linhas horizontais)
Grid tracks (trilhas): o espaço entre duas grid lines adjacentes
→ uma coluna é uma trilha vertical
→ uma linha é uma trilha horizontal
Grid area: retângulo formado por grid lines
→ pode abranger múltiplas células
Gap: espaço entre trilhas (anteriormente chamado de grid-gap)
Imagem sugerida: diagrama visual da grade com grid lines numeradas em azul, células destacadas em cinza claro, e um exemplo de grid area abrangendo múltiplas células em laranja — com labels de cada conceito.
(imagem será adicionada posteriormente)
As grid lines são numeradas a partir de 1, não de 0. Em uma grade de 3 colunas, as linhas verticais são numeradas 1, 2, 3 e 4. Também podem ser referenciadas de trás para frente com valores negativos: -1 é sempre a última linha, -2 a penúltima, etc.
9.1.4 — Grid vs Flexbox: escolhendo o modelo certo¶
A tabela abaixo complementa a visão apresentada no Capítulo 8, agora com o Grid disponível como referência concreta:
| Critério | Flexbox | Grid |
|---|---|---|
| Dimensões | 1D: linha ou coluna | 2D: linha e coluna |
| Ponto de partida | Conteúdo determina layout | Layout determina posição do conteúdo |
| Alinhamento | No eixo principal ou cruzado | Em ambos os eixos simultaneamente |
| Melhor para | Componentes (navbar, cards, forms) | Estruturas de página, galerias, dashboards |
| Posicionamento preciso | Limitado | Preciso por linhas e áreas nomeadas |
| Responsividade intrínseca | Via flex-wrap |
Via auto-fill/auto-fit + minmax() |
Na prática profissional, Grid e Flexbox são complementares e frequentemente usados juntos no mesmo projeto: Grid para a estrutura macro da página, Flexbox para os componentes internos.
Referência: MDN — CSS Grid Layout
9.2 — Definindo a grade: colunas e linhas¶
Vídeo curto explicativo (link será adicionado posteriormente)
9.2.1 — grid-template-columns e grid-template-rows¶
Estas duas propriedades definem a estrutura explícita da grade — quantas colunas e linhas existem, e qual o tamanho de cada trilha:
.container {
display: grid;
/* Três colunas: 200px, 1fr, 300px */
grid-template-columns: 200px 1fr 300px;
/* Duas linhas: primeira com 80px, segunda automática */
grid-template-rows: 80px auto;
}
/* Exemplos variados */
.grade-simples {
grid-template-columns: 1fr 1fr 1fr; /* três colunas iguais */
grid-template-columns: 25% 50% 25%; /* porcentagens */
grid-template-columns: 200px 1fr; /* fixa + flexível */
grid-template-columns: auto auto auto; /* automático pelo conteúdo */
}
9.2.2 — A unidade fr — fração do espaço disponível¶
A unidade fr (fraction) é exclusiva do CSS Grid e representa uma fração do espaço disponível no container após subtrair espaços fixos (colunas em px, %, gaps):
.container {
display: grid;
width: 900px;
gap: 20px;
/* Três colunas iguais: cada uma recebe 1/3 do espaço disponível */
grid-template-columns: 1fr 1fr 1fr;
/* Espaço disponível: 900px - (2 × 20px gap) = 860px → cada coluna ≈ 286px */
/* Proporções diferentes */
grid-template-columns: 2fr 1fr;
/* Coluna 1: 2/3 de 860px ≈ 573px | Coluna 2: 1/3 de 860px ≈ 287px */
/* Coluna fixa + coluna flexível */
grid-template-columns: 300px 1fr;
/* Coluna 1: 300px fixos | Coluna 2: 900px - 300px - 20px gap = 580px */
}
A distinção entre fr e % é importante: % é calculado sobre o tamanho total do container (incluindo gaps), enquanto fr é calculado sobre o espaço restante após descontar espaços fixos — tornando fr mais previsível em layouts com gaps.
9.2.3 — A função repeat()¶
repeat() evita a repetição manual de trilhas idênticas:
.container {
/* Sem repeat: verboso */
grid-template-columns: 1fr 1fr 1fr 1fr;
/* Com repeat: conciso */
grid-template-columns: repeat(4, 1fr);
/* Padrão repetido */
grid-template-columns: repeat(3, 1fr 2fr); /* 6 colunas: 1fr 2fr 1fr 2fr 1fr 2fr */
/* Valores mistos */
grid-template-columns: 200px repeat(3, 1fr) 200px;
/* resultado: 200px 1fr 1fr 1fr 200px */
/* Linhas também */
grid-template-rows: repeat(4, 150px);
grid-template-rows: 80px repeat(3, 1fr) 60px;
}
9.2.4 — A função minmax()¶
minmax(mínimo, máximo) define um intervalo de tamanho para uma trilha — ela pode crescer até o máximo e encolher até o mínimo:
.container {
/* Cada coluna tem no mínimo 200px e no máximo 1fr */
grid-template-columns: repeat(3, minmax(200px, 1fr));
/* Linhas com altura mínima, crescendo com o conteúdo */
grid-template-rows: repeat(4, minmax(100px, auto));
/* Sidebar com largura entre 200px e 300px */
grid-template-columns: minmax(200px, 300px) 1fr;
}
minmax() é especialmente útil em combinação com auto-fill/auto-fit para criar grids intrinsecamente responsivos.
9.2.5 — auto-fill vs auto-fit — grids intrinsecamente responsivos¶
Esta é uma das funcionalidades mais poderosas do CSS Grid: criar grades que se adaptam automaticamente ao espaço disponível sem nenhuma media query:
/* auto-fill: cria o máximo de colunas que caibam,
mantendo colunas vazias se houver espaço sobrando */
.grade-auto-fill {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 1.5rem;
}
/* auto-fit: cria o máximo de colunas que caibam,
mas EXPANDE as existentes para preencher o espaço vazio */
.grade-auto-fit {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
}
Container: 800px | minmax(250px, 1fr)
Em 800px → 3 colunas cabem (3 × 250px = 750px ≤ 800px)
Em 600px → 2 colunas cabem (2 × 250px = 500px ≤ 600px)
Em 300px → 1 coluna cabe
auto-fill com 2 itens em container de 800px:
[ item 1 ][ item 2 ][ ][ ]
↑ colunas vazias mantidas
auto-fit com 2 itens em container de 800px:
[ item 1 ][ item 2 ]
↑ colunas vazias colapsadas, itens expandem
Quando usar cada um:
- auto-fill: quando a grade deve manter sua estrutura mesmo com poucos itens (ex.: grade de produtos que pode ter uma ou muitas linhas)
- auto-fit: quando os itens devem expandir para preencher o container quando há poucos (ex.: cards que devem sempre cobrir a largura total)
9.3 — Posicionamento de itens¶
Vídeo curto explicativo (link será adicionado posteriormente)
9.3.1 — Fluxo automático do grid¶
Por padrão, os grid items são posicionados automaticamente nas células da grade em ordem — preenchendo linha por linha, da esquerda para a direita:
<div class="container">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
</div>
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
}
/* Resultado do fluxo automático:
[1][2][3]
[4][5] ← quinta célula vazia
*/
O fluxo automático é suficiente para a maioria dos casos — grades de cards, galerias, listas de produtos. O posicionamento explícito é necessário quando um item precisa ocupar uma posição ou tamanho específico na grade.
9.3.2 — grid-column e grid-row — posicionamento por linhas¶
grid-column e grid-row posicionam um item especificando entre quais grid lines ele deve se estender:
.item {
/* grid-column: linha-início / linha-fim */
grid-column: 1 / 3; /* da linha vertical 1 até a 3 (2 colunas) */
grid-row: 2 / 4; /* da linha horizontal 2 até a 4 (2 linhas) */
}
/* Exemplos */
.header {
grid-column: 1 / 4; /* ocupa todas as 3 colunas */
grid-row: 1 / 2; /* primeira linha */
}
.footer {
grid-column: 1 / -1; /* da primeira à última linha (-1 = última) */
grid-row: 4 / 5;
}
.destaque {
grid-column: 2 / 4; /* colunas 2 e 3 */
grid-row: 1 / 3; /* linhas 1 e 2 */
}
Referência por linha negativa: -1 sempre se refere à última grid line, -2 à penúltima, independentemente do número total de colunas ou linhas:
/* Ocupa a largura inteira da grade, independente de quantas colunas há */
.largura-total {
grid-column: 1 / -1;
}
9.3.3 — span — extensão por múltiplas células¶
Em vez de especificar a linha final, span indica quantas trilhas o item deve ocupar a partir de sua posição:
.item {
/* Equivalentes: ambos ocupam 2 colunas a partir da coluna 2 */
grid-column: 2 / 4;
grid-column: 2 / span 2;
/* Span sem posição inicial: o item ocupa 3 colunas a partir
de onde o fluxo automático o colocar */
grid-column: span 3;
grid-row: span 2;
}
span é especialmente útil em grades com fluxo automático onde a posição inicial não é determinística — apenas o tamanho do item é fixado:
/* Grade de galeria: algumas imagens são maiores */
.imagem-destaque {
grid-column: span 2;
grid-row: span 2;
/* ocupa 2×2 células, em qualquer posição que o fluxo colocar */
}
9.3.4 — grid-area — posicionamento com nome¶
grid-area é um shorthand que combina grid-row-start, grid-column-start, grid-row-end e grid-column-end:
.item {
/* grid-area: row-start / col-start / row-end / col-end */
grid-area: 1 / 2 / 3 / 4;
/* equivale a:
grid-row: 1 / 3;
grid-column: 2 / 4; */
}
O uso mais importante de grid-area, porém, é como identificador de área nomeada — explorado na próxima seção.
9.4 — Áreas nomeadas¶
Vídeo curto explicativo (link será adicionado posteriormente)
As áreas nomeadas são uma das funcionalidades mais expressivas do CSS Grid. Elas permitem declarar o layout da página como um mapa visual em ASCII diretamente no CSS — tornando o código autoexplicativo e extremamente fácil de modificar.
9.4.1 — grid-template-areas — definindo o mapa visual do layout¶
.pagina {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: 80px 1fr 60px;
grid-template-areas:
"header header"
"sidebar main "
"footer footer";
min-height: 100vh;
gap: 1rem;
}
A string de grid-template-areas é um mapa visual direto do layout: cada linha da string corresponde a uma linha da grade, cada palavra a uma célula. Células com o mesmo nome formam uma área retangular contígua.
Regra importante: áreas nomeadas devem ser sempre retangulares e contíguas. Não é possível criar uma área em L ou T, por exemplo. Tentativas de criar áreas não retangulares produzem um valor inválido ignorado pelo navegador.
9.4.2 — Atribuindo itens a áreas com grid-area¶
Depois de definir as áreas no container, cada item recebe o nome da área correspondente:
<div class="pagina">
<header class="cabecalho">Cabeçalho</header>
<nav class="barra-lateral">Sidebar</nav>
<main class="conteudo">Conteúdo Principal</main>
<footer class="rodape">Rodapé</footer>
</div>
.pagina {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: 80px 1fr 60px;
grid-template-areas:
"header header"
"sidebar main "
"footer footer";
min-height: 100vh;
gap: 1rem;
}
/* Cada item recebe o nome da sua área */
.cabecalho { grid-area: header; }
.barra-lateral { grid-area: sidebar; }
.conteudo { grid-area: main; }
.rodape { grid-area: footer; }
O resultado é um layout de página completo, semântico e visualmente declarado no CSS — sem nenhum posicionamento absoluto ou float.
9.4.3 — Células vazias com . (ponto)¶
Quando uma célula da grade não pertence a nenhuma área nomeada, usa-se . (ponto) como placeholder:
.dashboard {
display: grid;
grid-template-columns: 200px 1fr 1fr;
grid-template-rows: 60px repeat(3, 1fr);
grid-template-areas:
"nav header header "
"nav card-a card-b "
"nav card-c . " /* última célula vazia */
"nav footer footer ";
}
Múltiplos pontos na mesma célula (... ou . . .) também são válidos e equivalentes a um único ponto — alguns desenvolvedores usam múltiplos pontos para alinhar visualmente o mapa.
9.4.4 — Mudando o layout com media queries¶
Áreas nomeadas são especialmente poderosas para layouts responsivos — basta redefinir grid-template-areas em diferentes breakpoints:
/* Layout padrão: desktop */
.pagina {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: 80px 1fr 60px;
grid-template-areas:
"header header"
"sidebar main "
"footer footer";
gap: 1rem;
}
/* Layout tablet: sidebar abaixo do conteúdo */
@media (max-width: 1024px) {
.pagina {
grid-template-columns: 1fr;
grid-template-rows: 80px 1fr auto 60px;
grid-template-areas:
"header "
"main "
"sidebar"
"footer ";
}
}
/* Layout mobile: coluna única, sidebar oculta */
@media (max-width: 600px) {
.pagina {
grid-template-columns: 1fr;
grid-template-rows: 60px 1fr 60px;
grid-template-areas:
"header"
"main "
"footer";
}
.barra-lateral {
display: none;
}
}
/* Os itens NÃO precisam ser alterados — apenas o container muda */
.cabecalho { grid-area: header; }
.barra-lateral { grid-area: sidebar; }
.conteudo { grid-area: main; }
.rodape { grid-area: footer; }
Esta é uma das vantagens mais significativas das áreas nomeadas: os itens não precisam ser alterados nas media queries — apenas o mapa do container é redesenhado. Isso torna layouts responsivos complexos muito mais fáceis de manter.
9.5 — Alinhamento no Grid¶
Vídeo curto explicativo (link será adicionado posteriormente)
O Grid compartilha o sistema de alinhamento do Flexbox, mas com uma camada adicional de controle: é possível alinhar tanto os itens dentro de suas células quanto a grade inteira dentro do container.
9.5.1 — justify-items e align-items¶
Estas propriedades controlam como os itens são alinhados dentro de suas células:
justify-items: alinhamento no eixo inline (horizontal em escrita ocidental)align-items: alinhamento no eixo block (vertical)
.container {
display: grid;
grid-template-columns: repeat(3, 200px);
grid-template-rows: repeat(3, 150px);
/* Padrão: stretch — itens preenchem a célula */
justify-items: stretch; /* padrão */
align-items: stretch; /* padrão */
/* Centralizar todos os itens em suas células */
justify-items: center;
align-items: center;
/* Outros valores */
justify-items: start;
justify-items: end;
align-items: start;
align-items: end;
align-items: baseline;
}
justify-items: stretch (padrão) justify-items: center
┌──────────────────┐ ┌──────────────────┐
│ ┌──────────────┐ │ │ ┌────────┐ │
│ │ item │ │ │ │ item │ │
│ └──────────────┘ │ │ └────────┘ │
└──────────────────┘ └──────────────────┘
item preenche a célula item centralizado
9.5.2 — justify-content e align-content¶
Quando a grade é menor que o container (quando as trilhas têm tamanho fixo e há espaço sobrando), estas propriedades controlam como a grade como um todo é posicionada no container:
.container {
display: grid;
width: 900px;
height: 600px;
grid-template-columns: repeat(3, 200px); /* 3 × 200px = 600px < 900px */
grid-template-rows: repeat(2, 150px); /* 2 × 150px = 300px < 600px */
/* Distribuir as colunas no espaço disponível */
justify-content: center;
justify-content: space-between;
justify-content: space-evenly;
justify-content: start; /* padrão */
justify-content: end;
/* Distribuir as linhas no espaço disponível */
align-content: center;
align-content: space-between;
align-content: end;
align-content: start; /* padrão */
}
9.5.3 — justify-self e align-self¶
Sobrescrevem justify-items e align-items para um item específico:
.item-especial {
justify-self: end; /* alinha à direita na célula */
align-self: start; /* alinha no topo da célula */
}
.item-centralizado {
justify-self: center;
align-self: center;
}
.item-esticado {
justify-self: stretch; /* estica para preencher a célula */
align-self: stretch;
}
9.5.4 — place-items e place-content — shorthands¶
.container {
/* place-items: align-items justify-items */
place-items: center; /* centraliza em ambos os eixos */
place-items: start end; /* align: start | justify: end */
/* place-content: align-content justify-content */
place-content: center;
place-content: space-between center;
/* place-self (em itens): align-self justify-self */
}
.item {
place-self: center; /* centraliza o item na célula */
}
Centralização com Grid em duas linhas:
.container {
display: grid;
place-items: center;
min-height: 100vh;
}
/* O filho direto é centralizado horizontal e verticalmente */
9.6 — Grid implícito e controle de fluxo¶
Vídeo curto explicativo (link será adicionado posteriormente)
A grade explícita é a estrutura definida por grid-template-columns, grid-template-rows e grid-template-areas. Quando itens são posicionados fora dessa estrutura — seja por posicionamento explícito além dos limites ou por fluxo automático que ultrapassa as linhas definidas —, o navegador cria automaticamente uma grade implícita para acomodá-los.
9.6.1 — grid-auto-rows e grid-auto-columns¶
Controlam o tamanho das trilhas criadas automaticamente pelo grid implícito:
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
/* Apenas 1 linha explícita definida: 200px */
grid-template-rows: 200px;
/* Linhas adicionais (implícitas) criadas automaticamente */
grid-auto-rows: 150px;
/* Sem grid-auto-rows, as linhas implícitas teriam altura mínima pelo conteúdo */
}
/* Uso com minmax: linha implícita com altura mínima */
.container {
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(150px, auto);
/* cada linha tem no mínimo 150px e cresce com o conteúdo */
}
grid-auto-rows: minmax(150px, auto) é um padrão muito utilizado em grades de cards: garante altura mínima consistente mas permite que o card cresça se o conteúdo for maior.
9.6.2 — grid-auto-flow — direção do fluxo automático¶
Controla como itens sem posicionamento explícito são colocados na grade:
.container {
grid-auto-flow: row; /* padrão: preenche linha por linha */
grid-auto-flow: column; /* preenche coluna por coluna */
grid-auto-flow: row dense; /* linha por linha, preenchendo lacunas */
grid-auto-flow: column dense; /* coluna por coluna, preenchendo lacunas */
}
Com grid-auto-flow: column, as trilhas implícitas criadas são colunas (não linhas), e grid-auto-columns controla seu tamanho:
.container {
display: grid;
grid-template-rows: repeat(3, 100px); /* 3 linhas fixas */
grid-auto-flow: column; /* itens fluem por colunas */
grid-auto-columns: 150px; /* colunas implícitas com 150px */
}
9.6.3 — grid-auto-flow: dense — preenchimento de lacunas¶
Quando alguns itens têm span maior que outros, podem surgir lacunas na grade. O valor dense instrui o algoritmo de posicionamento a tentar preencher essas lacunas com itens menores que venham depois:
.galeria {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 200px;
grid-auto-flow: row dense; /* preenche lacunas com itens subsequentes */
gap: 1rem;
}
.imagem-grande { grid-column: span 2; grid-row: span 2; }
.imagem-larga { grid-column: span 2; }
.imagem-alta { grid-row: span 2; }
/* imagens normais não têm span */
Sem dense: Com dense:
[G][G][ ][ ] [G][G][A][B]
[G][G][A][ ] [G][G][C][D]
[L][L][B][C] [L][L][E][F]
↑ lacunas ↑ lacunas preenchidas
⚠️ Atenção:
densepode alterar a ordem visual dos itens em relação à ordem do DOM — itens menores podem "saltar" para posições anteriores para preencher lacunas. Assim como a propriedadeorderdo Flexbox, isso pode criar problemas de acessibilidade quando a ordem de apresentação é semanticamente relevante.
9.7 — Padrões práticos de layout com Grid¶
Vídeo curto explicativo (link será adicionado posteriormente)
9.7.1 — Layout de página completo¶
O padrão mais fundamental do CSS Grid: estrutura de página com header, sidebar, conteúdo principal e footer:
<body class="pagina">
<header class="cabecalho">
<h1>IFAL — Programação Web 1</h1>
<nav>...</nav>
</header>
<aside class="barra-lateral">
<nav aria-label="Sumário">...</nav>
</aside>
<main class="conteudo-principal">
<article>...</article>
</main>
<footer class="rodape">
<p>© 2026 IFAL</p>
</footer>
</body>
.pagina {
display: grid;
grid-template-columns: 260px 1fr;
grid-template-rows: 70px 1fr auto;
grid-template-areas:
"header header"
"sidebar main "
"footer footer";
min-height: 100vh;
gap: 0; /* gaps gerenciados por padding nos itens */
}
.cabecalho { grid-area: header; background: var(--cor-primaria); }
.barra-lateral { grid-area: sidebar; background: var(--cor-fundo); }
.conteudo-principal { grid-area: main; padding: 2rem; }
.rodape { grid-area: footer; background: var(--cor-primaria); }
/* Responsivo */
@media (max-width: 768px) {
.pagina {
grid-template-columns: 1fr;
grid-template-areas:
"header"
"main "
"footer";
}
.barra-lateral { display: none; }
}
9.7.2 — Grade de cards responsiva sem media queries¶
O padrão mais elegante do CSS Grid moderno: uma grade que se adapta completamente ao viewport sem uma única media query:
<section class="grade-cards">
<article class="card">...</article>
<article class="card">...</article>
<article class="card">...</article>
<!-- quantos cards forem necessários -->
</section>
.grade-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.5rem;
padding: 2rem;
}
.card {
display: flex; /* card interno usa Flexbox */
flex-direction: column;
background: white;
border-radius: var(--raio-borda);
box-shadow: var(--sombra-md);
overflow: hidden;
}
.card img {
width: 100%;
height: 200px;
object-fit: cover;
}
.card__corpo {
flex: 1;
padding: 1.5rem;
}
.card__rodape {
padding: 1rem 1.5rem;
border-top: 1px solid #eee;
}
Este padrão — repeat(auto-fit, minmax(280px, 1fr)) — é um dos mais valiosos do CSS moderno. Ele resolve automaticamente: em viewports largos, muitas colunas; em viewports estreitos, menos colunas; em mobile, coluna única. Tudo sem uma linha de media query.
9.7.3 — Layout de revista (magazine layout)¶
Layouts editoriais com elementos de tamanhos variados e posicionamento preciso:
<section class="revista">
<article class="artigo artigo--destaque">Artigo principal</article>
<article class="artigo artigo--secundario-a">Secundário A</article>
<article class="artigo artigo--secundario-b">Secundário B</article>
<article class="artigo artigo--pequeno-a">Pequeno A</article>
<article class="artigo artigo--pequeno-b">Pequeno B</article>
<article class="artigo artigo--pequeno-c">Pequeno C</article>
</section>
.revista {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(3, 250px);
gap: 1rem;
}
/* Artigo principal: ocupa 2 colunas e 2 linhas */
.artigo--destaque {
grid-column: 1 / 3;
grid-row: 1 / 3;
}
/* Secundários: uma coluna, duas linhas */
.artigo--secundario-a {
grid-column: 3 / 4;
grid-row: 1 / 3;
}
.artigo--secundario-b {
grid-column: 4 / 5;
grid-row: 1 / 3;
}
/* Pequenos: uma coluna, uma linha — fluxo automático na linha 3 */
/* (não precisam de posicionamento explícito) */
9.7.4 — Galeria de imagens com células de tamanho variado¶
Uma galeria onde algumas imagens são maiores, usando auto-flow: dense para preencher lacunas:
.galeria {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-auto-rows: 200px;
grid-auto-flow: dense;
gap: 0.5rem;
}
.galeria__item {
overflow: hidden;
border-radius: var(--raio-borda-sm);
}
.galeria__item img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 300ms ease;
}
.galeria__item:hover img {
transform: scale(1.05);
}
/* Imagens de destaque */
.galeria__item--largo { grid-column: span 2; }
.galeria__item--alto { grid-row: span 2; }
.galeria__item--grande { grid-column: span 2; grid-row: span 2; }
9.8 — Grid e acessibilidade¶
Vídeo curto explicativo (link será adicionado posteriormente)
9.8.1 — Ordem do DOM vs ordem visual no Grid¶
Assim como no Flexbox, o CSS Grid permite separar a ordem visual dos elementos da sua ordem no DOM — por meio de posicionamento explícito, grid-auto-flow e order. As mesmas implicações de acessibilidade se aplicam:
- Leitores de tela leem o conteúdo na ordem do DOM
- Navegação por teclado segue a ordem do DOM
- Seleção de texto segue a ordem do DOM
Portanto, qualquer reordenação visual que altere a sequência semântica do conteúdo viola o critério WCAG 2.1 1.3.2 — Sequência com Significado (nível A).
/* PROBLEMÁTICO: ordem visual desconectada do DOM */
.artigo-principal { grid-area: destaque; } /* visualmente primeiro */
.artigo-recente { grid-area: topo; } /* visualmente segundo */
/* No DOM, artigo-recente vem antes de artigo-principal —
leitor de tela lê recente antes de principal */
9.8.2 — Boas práticas de reordenação responsiva¶
A reordenação por media queries com grid-template-areas é geralmente segura quando aplicada a componentes onde a ordem não é semanticamente crítica. A regra prática:
Seguro: reordenar componentes de layout estrutural (mover sidebar de baixo para o lado, por exemplo) quando ambas as posições fazem sentido para a leitura.
Problemático: reordenar conteúdo sequencial (etapas, artigos em ordem cronológica, listas de prioridade) onde a posição visual comunica importância ou sequência.
/* SEGURO: sidebar pode estar em qualquer posição */
@media (max-width: 768px) {
.pagina {
grid-template-areas:
"header"
"main " /* main antes da sidebar em mobile */
"sidebar"
"footer";
}
}
/* O conteúdo principal ainda faz sentido independente da posição da sidebar */
/* PROBLEMÁTICO: etapas reordenadas visualmente */
@media (max-width: 768px) {
.processo {
grid-template-areas:
"etapa-3" /* visualmente primeiro em mobile */
"etapa-1"
"etapa-2";
}
}
/* Leitor de tela ainda lê etapa-1, etapa-2, etapa-3 na ordem do DOM */
Solução quando a reordenação é inevitável: reorganize o DOM para corresponder à ordem de leitura desejada e use Grid para a apresentação visual em desktop — não o contrário.
Referências: - MDN — CSS Grid Layout - W3C — CSS Grid Layout Module Level 1 - CSS Tricks — A Complete Guide to Grid - Grid Garden — exercício interativo - Layout Land — Jen Simmons (YouTube)
Atividades — Capítulo 9¶
1. Uma grade tem grid-template-columns: repeat(3, 1fr) em um container de 900px com gap: 30px. Qual é a largura de cada coluna?
2. Qual é a diferença prática entre auto-fill e auto-fit em repeat(auto-fill/auto-fit, minmax(200px, 1fr))?
3. Por que o uso de grid-auto-flow: dense pode criar problemas de acessibilidade?
4. Qual é a vantagem de usar grid-template-areas com media queries em vez de redefinir grid-column e grid-row nos itens?
- GitHub Classroom: Construir uma página de dashboard com: (1) layout de página completo usando
grid-template-areascom responsividade para mobile via media query; (2) grade de cards responsiva comauto-fit+minmax()sem media queries; (3) seção de destaque com posicionamento explícito por linhas (grid-column: span). (link será adicionado)
:material-arrow-left: Voltar ao Capítulo 8 — Layout com Flexbox :material-arrow-right: Ir ao Capítulo 10 — Design Responsivo