Existem muitos tutoriais e guias pelas webs que ensinam a trabalhar com CSS Grid, em geral. Inclusive, temos um curso completo sobre CSS Grid que você pode assistir de grátis.
Mas o que nem sempre é mostrado é a possibilidade do uso da função minmax()
para acrescentar um grau extra de controle e dinamicidade nos layouts feitos com CSS Grid.
Neste artigo, será mostrado, justamente, vamos nos aprofundar no minmax()
e aprender como, quando e por que usar minmax()
com CSS Grid e como isso pode trazer um poder impressionante a layouts e à responsividade em geral.
Introdução a layouts com CSS Grid e minmax()
Se você ainda não tinha ouvido falar, minmax()
faz o seguinte: define um intervalo de tamanho maior ou igual a min
e menor ou igual a max
.
E é possível usar minmax()
como um valor para definir colunas ou linhas de uma Grid. Veja um exemplo básico:
1 2 3 4 5 |
.o-grid { display: grid; grid-template-columns: minmax(200px, 500px) 1fr 1fr; grid-gap: 1rem; } |
Analisando:
- Foi especificada uma grid com 3 colunas;
- A largura da primeira coluna é
minmax(200px, 500px)
, ou seja, o valor mínimo é200px
e o valor máximo é500px
; - As outras 2 colunas têm
1fr
cada, significando que elas ocuparão o espaço restante disponível.
Rumando para preocupações mais condizentes a layouts do mundo real, é preciso começar pensar na responsividade disso.
O que acontece quando o tamanho da viewport é muito pequena? A resposta curta é: barra de rolagem horizontal. E ninguém gosta de ver uma barra de rolagem horizontal — a não ser que tenha sido planejada.
Isso significa que minmax()
não consegue lidar sozinho com web design responsivo; é preciso que o dev dê um talento no código para ficar certinho. Mais sobre isso daqui a pouco.
Validação de layouts com CSS Grid e minmax()
Se o valor “min” em minmax(min, max)
for maior que “max”, o máximo será ignorado e tudo será tratado como um valor mínimo.
Além disso, é importante ter em mente que usar 1fr
para o valor mínimo é inválido. Isso é pior do que o mínimo ser maior que o máximo! Toda a declaração será ignorada.
Usar zero para o valor mínimo de minmax()
O que será que acontece ao usar minmax(0, 500px)
?
A largura será pelo menos zero e não ultrapassará 500px. Isso significa que, se a largura da viewport não for suficiente, a largura da coluna será redimensionada.
Uma grid simples
Num exemplo de uma grid simples, suponhamos que é preciso criar uma grdde de 3 colunas:
1 2 3 4 5 |
.o-grid { display: grid; grid-template-columns: minmax(200px, 1fr) minmax(200px, 1fr) minmax(200px, 1fr); grid-gap: 1rem; } |
Se for da preferência do freguês leitor, seria possível usar repeat()
para um código mais enxuto:
1 2 3 4 5 |
.o-grid { display: grid; grid-template-columns: repeat(3, minmax(200px, 1fr)); grid-gap: 1rem; } |
De qualquer maneira, isso não é recomendado, já que não funcionaria da maneira que a maioria pode estar imaginando, pois causaria uma barra de rolagem horizontal. 🤢
Barra de rolagem horizontal
Pois é… Usar minmax() com CSS Grid para layouts dessa maneira, a depender do tamanho da viewport, pode causar uma barra de rolagem horizontal.
Como se está definindo explicitamente o número de colunas, o navegador não pode fazê-las quebrar (wrap) quando a largura da viewport for pequena. Como resultado, isso causará uma barra de rolagem horizontal.
Para consertar essa barra de rolagem horizontal, é preciso informar ao navegador que o número de colunas deverá diminuir se a largura da viewport não for o bastante.
Se o caso fosse Flexbox, seria possível fazer usando flex-wrap: wrap
.
1 2 3 4 |
.parent { display: flex; flex-wrap: wrap; } |
Com CSS Grid, é possível usar as palavras-chave auto-fit
ou auto-fill
.
Usar auto-fit
ou auto-fill
Para evitar ajustes nos problemas mencionados acima, é possível obter os benefícios das palavras-chave auto-fit
ou auto-fill
. A diferença entre uma e outra é sutil, mas significativa.
Resumidamente, auto-fit
expandirá os itens da grid para preencher o espaço disponível, enquanto auto-fill
manterá o espaço disponível reservado sem alterar a largura dos itens da grid.
Em determinados casos, dependendo do tamanho da viewport, usar auto-fill/fit poderá produzir o mesmo resultado, no entanto, essa semelhança não será notada até que se redimensione a viewport.
Casos de uso e exemplos
Cards Grid
Um caso clássico para o uso de CSS Grid e minmax()
é a criação de um wrapper de cards responsivos.
1 2 3 4 5 |
.wrapper { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); grid-gap: 1rem; } |
Quando se começa a aprender CSS Grid, não é incomum achar assustador ler o valor de grid-template-columns
. É importante prestar atenção às viewports abaixo de 250px
, pois haverá uma barra de rolagem horizontal.
Para resolver isso, há, pelo menos, 2 soluções. A primeira é usar CSS media queries. A ideia é definir grid-template-columns
para 1fr
e, quando a largura da viewport for grande o suficiente, aplicar o minmax()
.
1 2 3 4 5 6 7 8 9 10 11 |
.wrapper { display: grid; grid-gap: 1rem; grid-template-columns: 1fr; } @media (min-width: 300px) { .wrapper { grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); } } |
A segunda solução é usar funções de comparação CSS.
1 2 3 4 5 6 7 8 |
.wrapper { display: grid; grid-gap: 1rem; grid-template-columns: repeat( auto-fill, minmax(min(100%, 250px), 1fr) ); } |
Ao usar a função de comparação min()
como o primeiro valor para minmax()
, eis o que está acontecendo:
- Se a largura da viewport for menor que
250px
, o primeiro valor da funçãominmax()
será100%
da largura do elemento-pai; - Se a largura da viewport for maior que
250px
, o primeiro valor deminmax()
será250px
.
Uso da unidade ch
para um wrapper de conteúdo
Um caso de uso interessante para minmax()
é usá-lo para criar um layout de artigo. Para este exemplo, o conteúdo é centralizado horizontalmente.
1 2 3 4 5 |
.wrapper { display: grid; grid-gap: 1rem; grid-template-columns: minmax(1rem, 1fr) minmax(auto, 70ch) minmax(1rem, 1fr); } |
A primeira e a última colunas funcionam como gutters; a do meio é a mais importante. Observe que ela tem minmax(auto, 70ch)
.
Isso significa que a largura máxima para essa coluna é de 70 caracteres por linha. Esse é um comprimento de caractere ideal para melhor legibilidade.
A técnica também faz com que tudo funcione muito bem em dispositivos móveis (responsivo sem media queries), já que a primeira e a última colunas serão recolhidas com uma largura mínima de 1rem.
A desvantagem em usar auto-fit
de forma irresponsável
Por tudo o que foi mostrado, pode ser tentador usar auto-fit
para todos os layouts com CSS Grid.
Mas a desvantagem é que, quando o conteúdo é dinâmico e você não tem controle, as coisas podem quebrar facilmente.
1 2 3 4 5 |
.wrapper { display: grid; grid-gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); } |
Uma grid de cards, por exemplo, pode parece perfeita em 4 colunas. No entanto, quando há apenas um card, ela se expande para preencher o espaço restante disponível.
O motivo é que se o componente do card tiver uma imagem com texto, por exemplo, ele expandirá a imagem para preencher a largura total, o que faz com que a imagem pareça extremamente ruim.
Por isso é interessante que você sempre use auto-fit
para fazer layouts com CSS Grid de maneira consciente.
Se o componente que você estiver trabalhando tem uma mídia a ser exibida, outras abordagens talvez sejam mais interessantes.
Conclusão
Fazer layouts usando CSS Grid com minmax()
, auto-fit
ou auto-fill
faz parte das técnicas de fazer layouts responsivos e eficientes usando CSS moderno.
É importante que você se atualize e use as técnicas mais recentes para layouts com CSS Grid, mas faça de maneiras consciente, para não gerar bugs visuais desnecessários.