O Grid Layout é um sistema para criação de layout baseado em uma grade bidimensional e otimizado para design de interfaces de usuário. Nesse modelo de grade, os elementos filhos do container que define a grade podem ser posicionados livremente em espaços criados na estrutura, quer ela tenha sido definida com suas dimensões flexíveis ou fixas.
Basicamente, vamos dividir um site em linhas e colunas, como uma grade, para organizar o mesmo, de forma semelhante a uma matriz. O site, no entanto, pode se adaptar a uma tela menor, como a de um celular.
Em versões mais antigas do HTML, era comum usarmos tabelas pra montar a estrutura de um site. As tabelas existem até hoje no HTML5, mas não é prático usar elas pra estruturar um site, o Grid Layout faz isso de forma muito mais fluída e responsiva.
Vamos supor um grid 6 × 6 (6 linhas e 6 colunas), a linha é chamada em inglês de row
e a coluna de column
(atenção que existe o line
também mas ele é usado em algo diferente, no caso, das barras que dividem os itens). Um container é o grid em si (a parte de fora) e cada um elemento dentro dele é chamado de item. Uma linha ou coluna de forma generalizada, é chamada de track
, mais especificamente row track
e column track
. Um grid 6 × 6 tem sete lines contadas a partir do 1, a partir da esquerda e de cima, e temos também a numeração inversa, com números negativos, contados a partir da direita e de baixo. Veja essa imagem abaixo:
Na imagem acima, temos uma área que vai da line 2 até a -2 (penúltima, que no caso é 6). Uma área pode ter uma quantidade ilimitada de linhas e colunas, e elas podem ter um respiro
entre elas, que é o que chamamos de gap
, e pode ter tamanho variável, que não interferem no tamanho dos itens.
O container do Grid Layout tem algumas propriedades específicas, que são display, grid-template-columns, grid-template-rows e gap. Existem outras, mas primeiramente vamos focar nessas.
Vamos exemplificar num grid 3 × 3, que tem 3 tracks e cada track tem 4 lines. A linha da parte de fora é o grid container, que no caso do Grid, é bidimensional (no FlexBox é unidimensional). Para especificar que é um grid, nós colocamos display: grid.
Vamos supor esse HTML:
<div class="container">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
<div class="item">D</div>
<div class="item">E</div>
<div class="item">F</div>
<div class="item">G</div>
</div>
Com esse CSS:
div.container {
display: grid;
grid-template-columns: auto auto auto;
grid-template-rows: 100px 100px 100px;
gap: 20px;
}
div.item {
background-color: lightgray;
}
Ao colocar apenas display: grid ele não faz nada praticamente, pois automaticamente ele é um grid de uma coluna e várias linhas. Para isso devemos colocar as outras opções para os configurar. Ao colocar grid-template-columns: auto auto ele criará um grid com duas colunas (se tiver auto auto auto terá três, e assim por diante). A mesma coisa se aplica ao grid-template-rows: 100px 100px 100px para linhas, que no caso, definimos um tamanho padrão. O gap: 20px cria um espacinho definido entre os itens, e podemos ter configurações específicas pra colunas e linhas também.
Para começar, no index.html coloque esse código:
<div class="container">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
<div class="item">D</div>
<div class="item">E</div>
<div class="item">F</div>
<div class="item">G</div>
</div>
Com esse estilo:
div.container {
border: 3px solid blue;
height: 250px;
display: grid;
}
div.item {
border: 3px solid red;
padding: 5px;
}
Lembrando que, à primeira vista, o container pode não mudar nada, mas ele se torna sim um Grid, mas teremos que colocar outras configurações pra ele funcionar.
Deixe o CSS do container assim:
div.container {
border: 3px solid blue;
height: 250px;
display: grid;
grid-template-columns: auto auto auto;
grid-template-rows: auto auto auto;
gap: 5px;
}
No caso acima, ele terá um Grid com três linhas e três colunas, de tamanho auto.
Ao abrir o Inspecionar Elemento do navegador, em Inspetor e Layout (pode variar de navegador pra navegador), podemos clicar no elemento HTML, que estará marcado com grid
, e ele mostrará os elementos do Grid, onde poderemos ver inclusive a numeração do container. Podemos brincar
um pouco com os elementos ali, como, por exemplo, o tamanho do gap.
Temos várias outras propriedades para usarmos pelo Grid Layout, o align-items, o justify-items, o align-content e o justify-content, onde os align
são para alinhamento vertical e o justify
são pra alinhamento horizontal.
Usando o mesmo HTML do exemplo anterior, vamos colocar esse CSS:
div.container {
border: 3px solid blue;
display: grid;
grid-template-columns: auto auto auto;
grid-template-rows: 100px 100px 100px;
}
div.item {
border: 3px solid red;
padding: 5px;
}
No container, vamos deixar o CSS assim:
div.container {
border: 3px solid blue;
display: grid;
grid-template-columns: auto auto auto;
grid-template-rows: 100px 100px 100px;
align-items: stretch;
justify-items: stretch;
}
div.item {
border: 3px solid red;
padding: 5px;
}
O stretch é o padrão pra align-items, caso não coloquemos nada, ele estica
verticalmente. Podemos colocar também os valores start, center e end. Brinque
com essas opções, mas vamos trabalhar com o stretch. O mesmo vale pro justify-items, que ajusta horizontalmente.
Agora colocaremos o align-content e o justify-content, ele alinhará todo o conteúdo da grade, sendo o primeiro verticalmente e o segundo horizontalmente. O padrão de ambos é o stretch, mas podemos colocar os valores start, center, end, space-between, space-evenly e space-around, de forma semelhante ao que acontecia no FlexBox. Deixe o CSS assim e depois brinque
um pouco com essas opções:
div.container {
border: 3px solid blue;
height: 500px; /* Aumentando o container para vermos o espaçamento */
display: grid;
grid-template-columns: auto auto auto;
grid-template-rows: 100px 100px 100px;
align-items: stretch;
justify-items: stretch;
align-content: start;
justify-content: start;
}
Após terminar de brincar
, deixe as opções dos content
como stretch.
Com o mesmo HTML dos itens de A a G, deixe o CSS assim:
div.container {
border: 3px solid blue;
height: 500px;
display: grid;
grid-template-columns: auto auto auto;
grid-template-rows: auto auto auto;
gap: 10px;
}
div.item {
border: 3px solid red;
padding: 5px;
}
Deixe o CSS do container assim:
div.container {
border: 3px solid blue;
height: 500px;
display: grid;
grid-template-columns: auto auto auto;
grid-template-rows: auto auto auto;
gap: 10px;
align-items: normal;
justify-items: normal;
align-content: normal;
justify-content: normal;
}
Como visto, o normal
é o stretch (esticar).
Tente em cada um dos itens, além do stretch, o start, center e end.
Tente em cada um dos content, além do stretch, start, center, end, space-between, space-evenly e space-around.
Ainda temos mais propriedades de container para o Grid Layout, como o grid-auto-rows, grid-auto-columns, place-items, place-content e grid-template, sendo que os três últimos são simplificações de propriedades vistas anteriormente. Vamos continuar com o HTML de A a G, e coloque o H e o I também, com esse CSS:
div.container {
border: 3px solid blue;
display: grid;
grid-template-columns: auto auto auto;
grid-template-rows: 100px 100px 100px;
}
div.item {
border: 3px solid red;
padding: 5px;
}
No caso acima, o container terá só 9 itens, se colocarmos um 10º item, ele não ficará encaixado, porque nosso Grid explícito tem três colunas e três linhas (o Grid definido é chamado de Grid explícito), que comporta 9 itens, e o J
não seguirá a mesma configuração e ficará espremido
. Poderíamos colocar mais um 100px, mas caso o J
saia, ficará um espaço de 100px vazio. Ao colocar grid-auto-rows: 100px, podemos ter um Grid de 9 colunas sem problemas ao adicionar mais itens que isso implicitamente (os itens fora do Grid são do Grid implícito), deixando o CSS do container assim:
div.container {
border: 3px solid blue;
display: grid;
grid-template-columns: auto auto auto;
grid-template-rows: 100px 100px 100px;
grid-auto-rows: 100px;
}
Da mesma forma, usamos o grid-auto-columns para as colunas, mas esse costuma ser menos usado.
Deixe as divs de A a I, e deixe o CSS do container assim:
div.container {
border: 3px solid blue;
display: grid;
grid-template-columns: auto auto auto;
grid-template-rows: 100px 100px 100px;
align-items: stretch;
justify-items: center;
align-content: start;
justify-content: end;
}
O align-items e o justify-items podemos simplificar com o place-items, que configura ambos numa propriedade só. O mesmo vale pro place-content, que simplifica o align-content e justify-content. A configuração de ambos os place configura primeiro o align (vertical) e depois o justify (horizontal). Veja como fica o CSS acima simplificado:
div.container {
border: 3px solid blue;
display: grid;
grid-template-columns: auto auto auto;
grid-template-rows: 100px 100px 100px;
place-items: stretch center;
place-content: start end;
}
Da mesma forma, podemos simplificar o grid-template-rows e o grid-template-columns por simplesmente grid-template que configura os dois juntos, primeiro a linha e depois a coluna. O CSS ficaria assim:
div.container {
border: 3px solid blue;
display: grid;
grid-template: 100px 100px 100px / auto auto auto; /* a barra divide a linha da coluna */
place-items: stretch center;
place-content: start end;
}
Podemos ainda simplificar mais coisas, vamos voltar com os itens de A a G, com esse CSS:
div.container {
border: 3px solid blue;
display: grid;
grid-template-columns: auto auto auto;
grid-template-rows: 100px 100px 100px;
}
Podemos usar a função repeat() para repetir valores iguais numa propriedade, dessa forma:
div.container {
border: 3px solid blue;
display: grid;
grid-template-columns: repeat(3, auto);
grid-template-rows: repeat(3, 100px);
}
Simplificando:
div.container {
border: 3px solid blue;
display: grid;
grid-template: repeat(3, 100px) / repeat(3, auto);
}
Temos também a fr (fraction, ou fração). Para usar as frações, vamos supor um container bem grande, que tenha 1500px de largura, com a propriedade grid-template-columns: auto auto auto para ele criar três itens em três colunas cada um com a mesma largura (que no caso, é 500px pra cada). Podemos substituir por grid-template-columns: 1fr 1fr 1fr pra dividir de forma melhor do que o auto
, independente do tamanho da tela, onde cada 1fr
é um item. Podemos configurar valores diferentes pra cada célula com as frações, como o valor 1fr 2fr 1fr, onde a coluna do meio é o dobro das outras, onde dividimos em três partes, mas quatro frações (de 375px cada, a do meio tem duas partes de 375px, que é 750px).
Vamos supor uma declaração doida no mesmo container, como grid-template-columns: 100px 20% 1fr 1fr, onde o primeiro elemento tem 100px, o segundo tem 20% do tamanho do container (300px), e as duas últimas frações só serão feitas com o que sobrou
, que é 1100px, e cada fração ficará com 550px. Isso é menos usado e não é recomendado usar, mas pode ser encontrado em alguns sites. A mesma declaração também pode ter o repeat (no caso ficaria 100px 20% repeat(2, 1fr)).