Um grid em três linhas
Defina display: grid em um contêiner e liste as colunas com grid-template-columns. Os filhos preenchem as células em ordem, da esquerda para a direita em português, e uma nova linha começa sempre que as colunas estão cheias:
Sete itens, três colunas: duas linhas completas e uma terceira linha com o item 7 na primeira coluna. Todas as colunas têm a mesma largura, e todos os itens de uma linha têm a mesma altura, então as bordas se alinham nas duas direções. É isso que o grid acrescenta em relação ao flexbox.
Playground de grid
Digite qualquer valor de grid-template-columns ou clique em um preset. O painel mostra as larguras de coluna que o navegador calculou (com getComputedStyle) e quantas linhas os itens precisaram:
Algumas coisas para observar: 1fr 2fr deixa a segunda coluna com exatamente o dobro da primeira. 200px 1fr mantém os 200px e dá o resto para a segunda coluna. auto 1fr auto dimensiona as colunas das pontas pelo conteúdo. repeat(4, 100px) deixa espaço vazio no fim, porque nada é flexível. Um valor inválido, como 1fr 2, é ignorado, e o grid mantém o último valor válido.
A unidade fr
fr significa "uma parte do espaço livre". O navegador primeiro tira as colunas fixas (px, rem, %, conteúdo auto) e os gaps, e depois divide o que sobra entre as colunas fr de acordo com os números delas.
grid-template-columns em um contêiner de 600px, sem gap | Larguras das colunas |
|---|---|
1fr 1fr 1fr | 200, 200, 200 |
1fr 2fr | 200, 400 |
100px 1fr 1fr | 100, 250, 250 |
1fr 50% | 300, 300 |
fr não é o mesmo que %: porcentagens mais gaps podem somar mais de 100% e transbordar, enquanto as colunas fr sempre dividem só o que sobra depois dos gaps.
repeat(), minmax() e um grid responsivo sem media queries
repeat(4, 1fr) é 1fr 1fr 1fr 1fr. minmax(120px, 1fr) é uma coluna que nunca fica mais estreita que 120px e cresce para pegar uma parte. Junte os dois com auto-fill ou auto-fit no lugar de uma quantidade, e o grid cria tantas colunas quantas couberem:
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 16px;
}
Essa única declaração dá tantas colunas de pelo menos 180px quantas o contêiner comporta: várias em uma tela larga, uma no celular, sem nenhuma media query. A diferença entre auto-fill e auto-fit aparece quando há menos itens que colunas:
O contêiner comporta cinco colunas de 100px. auto-fill mantém as cinco, então A, B e C ficam com 112px cada e sobram duas colunas vazias. auto-fit colapsa as vazias, então os três itens se esticam para uns 187px cada.
Posicionar itens: grid-column e grid-row
As linhas do grid são numeradas a partir de 1 na borda inicial. grid-column: 1 / 3 significa "da linha 1 até a linha 3", ou seja, duas colunas. span 2 significa "duas colunas a partir de onde você cair", e -1 é a última linha:
O item escuro ocupa a primeira linha inteira. O azul cobre um bloco de 2 por 2, e o âmbar duas linhas. Os itens a e b preenchem sozinhos as células que sobram: o grid coloca cada item que pode na próxima célula livre. grid-auto-rows: 60px define a altura das linhas que você não declarou com grid-template-rows.
grid-template-areas: dê nome às partes de um layout
Para um layout de página, dê nome às áreas e desenhe-as como texto. Cada string é uma linha, cada palavra uma célula, e um item entra em uma área com grid-area:
O cabeçalho e o rodapé ocupam as duas colunas porque os nomes deles preenchem as duas células das respectivas linhas. A linha do meio é 1fr, então pega a altura que sobrar dos 280px. Para empilhar tudo no celular, uma media query só precisa redesenhar as áreas como uma coluna: grid-template-areas: "header" "side" "main" "footer" com grid-template-columns: 1fr. A página de media queries mostra o padrão.
Alinhar dentro das células
Por padrão, os itens do grid se esticam para preencher a célula. Estas propriedades os movem dentro dela:
| Propriedade | Em | Move |
|---|---|---|
justify-items | contêiner | todos os itens ao longo da linha (eixo inline) |
align-items | contêiner | todos os itens para cima e para baixo (eixo de bloco) |
place-items | contêiner | shorthand: place-items: center centraliza nos dois |
justify-self / align-self | item | um item |
justify-content / align-content | contêiner | o conjunto inteiro de trilhas, quando o grid é menor que o contêiner |
display: grid; place-items: center; é o jeito mais curto de centralizar um filho em uma caixa.
Grid ou flexbox
O grid é bidimensional: você decide as colunas (e as linhas), e o conteúdo as preenche, então todos os cards de uma galeria têm a mesma largura, até na última linha. O flexbox é unidimensional: os itens se dimensionam pelo conteúdo ao longo de uma única linha. Os dois combinam bem: um grid para a página e para a galeria de cards, flexbox dentro de cada card para a linha do cabeçalho. A página do flexbox cobre a outra metade.
Ordem e acessibilidade
grid-template-areas, grid-row, grid-column e order podem colocar um item em qualquer lugar, mas os leitores de tela e a tecla Tab continuam seguindo a ordem do HTML. Mantenha a ordem do código com sentido (cabeçalho, navegação, conteúdo principal, rodapé) e use o grid para arrumá-la, não para consertar uma ordem de HTML que não faz sentido.
Erros comuns
- Colocar
display: gridnos itens. Ele vai no pai; só os filhos diretos são itens do grid. - Usar porcentagens com gaps.
grid-template-columns: 50% 50%maisgap: 16pxtransborda 16px. Use1fr 1fr. auto-fillquando você queriaauto-fit. Com poucos itens,auto-filldeixa colunas vazias. Troque paraauto-fitpara esticar os itens.- Uma coluna
1frque cresce além da parte dela. Uma coluna1frnão encolhe abaixo do conteúdo mais longo (uma URL longa, uma imagem larga). Useminmax(0, 1fr)para deixá-la encolher. - Strings de área que não formam retângulos. Toda área nomeada precisa formar um retângulo, e todas as strings de linha precisam ter o mesmo número de células, senão a declaração
grid-template-areasinteira é ignorada. - Esquecer que a numeração das linhas começa em 1. Três colunas têm quatro linhas:
1 / 4ou1 / -1ocupa as três.
Perguntas frequentes
O que é CSS grid?
Um sistema de layout que posiciona elementos em linhas e colunas ao mesmo tempo. Você define display: grid em um contêiner, descreve as colunas com grid-template-columns (e, se quiser, as linhas), e os filhos diretos preenchem as células em ordem.
O que significa 1fr no CSS grid?
fr é uma fração do espaço livre no contêiner grid. grid-template-columns: 1fr 1fr 1fr dá três colunas iguais, e 1fr 2fr deixa a segunda coluna com o dobro da largura da primeira. Tamanhos fixos e gaps saem primeiro; as colunas fr dividem o que sobra.
Qual a diferença entre auto-fill e auto-fit?
Os dois criam tantas colunas quantas couberem. auto-fill mantém as colunas vazias, então poucos itens continuam estreitos e deixam espaço vazio no fim da linha. auto-fit colapsa as colunas vazias, então os itens se esticam para preencher a linha. Com itens suficientes para encher a linha, os dois ficam iguais.
Como fazer um item do grid ocupar duas colunas?
Use grid-column: span 2 no item, ou dê a ele linhas de início e fim: grid-column: 1 / 3 cobre as colunas 1 e 2. grid-column: 1 / -1 ocupa a largura toda, porque -1 é a última linha.
Quando usar grid em vez de flexbox?
Use grid quando linhas e colunas precisam se alinhar entre si: galerias de cards, formulários com rótulos alinhados, uma página com cabeçalho, barra lateral e rodapé. Use flexbox para uma única linha ou coluna cujos itens se dimensionam pelo conteúdo, como uma barra de navegação.
grid-gap é o mesmo que gap?
Sim. grid-gap, grid-row-gap e grid-column-gap são os nomes antigos. Os navegadores ainda os aceitam como apelidos, mas escreva gap, row-gap e column-gap, que também funcionam no flexbox.