# CSS Grid intrinsecamente responsiva com minmax() e min()

> CSS Grid intrinsecamente responsiva: layouts que se adaptam sozinhos. Domine minmax(), min() e técnicas para grids sem media queries. Revolucionário!

URL: https://dpw.dev/css/css-grid-intrinsecamente-responsiva-minmax-min/  
Publicado em: 2019-09-09  
Categoria: css  
Tags: css-grid, layout  
Autor: Tárcio Zemel

CSS Grid já é amplamente suportado em navegadores modernos, e muitas pessoas estão trabalhando muito bem com a real tecnologia de layouts para a Web!

> Artigo baseado em [Intrinsically Responsive CSS Grid with minmax() and min()](https://evanminto.com/blog/intrinsically-responsive-css-grid-minmax-min/).

Mas, infelizmente, um dos recursos mais úteis da especificação não funciona como anunciado, a **intrinsically responsive grid** ou **grid intrinsecamente responsiva** -- quer dizer, uma grid responsiva com base no tamanho de seu contêiner, sem o uso de media queries.

Mas, graças a alguns padrões que agora estão disponíveis em alguns navegadores e a caminho de outros, é possível contornar essa limitação!

Mas antes de explicar a solução, vamos revisar o problema. Com CSS Grid, é possível criar uma grid de itens organizados em colunas de tamanhos iguais e solicitar que os tamanhos das colunas sejam ajustados com base na quantidade de espaço disponível:

[Exemplo no CodePen](https://codepen.io/anon/pen/dBawwg)

Se quiser ter uma visão melhor do quê realmente o exemplo oferece, abra o pen diretamente no seu navegador e redimensione o tamanho da viewport.

Essa técnica usa vários recursos da especificação de CSS Grid:

- `repeat()` diz ao Grid para criar várias tracks com os mesmos parâmetros de tamanho (não necessariamente o mesmo tamanho, embora, neste caso, todos acabem sendo os mesmos).
- `auto-fill` diz para criar quantas tracks forem necessárias para preencher o espaço.
- `minmax(10rem, 1fr)` serve para determinar o tamanho de cada track, encontrando um valor entre um mínimo de `10rem` e um máximo de `1fr` (a unidade `fr` é o que garante que as tracks cresçam para preencher qualquer espaço restante).

> **Curso:** Caso tenha dúvidas sobre as terminologias usadas ou a sintaxe de funções, [faça nosso curso completo de CSS Grid grátis](https://www.youtube.com/watch?v=q_WV9exilhk&list=PLYgzkrmJnLwpeeGgdADYq3cE2yUwLLTOv)!

Graças a tudo isso, o contêiner adiciona novas colunas à medida que cresce. Um recurso principal desta solução é que as colunas mudam com base no tamanho do contêiner, não no tamanho da viewport, sempre parecerá correto, sem a necessidade de media queries substituindo o comportamento padrão em páginas específicas.

Mas, então, qual é o problema?

## Responsivo... Mas nem tanto

Como cada grid track tem um tamanho mínimo de `10rem`, elas não podem encolher abaixo desse tamanho. Isso significa que, quando o container é menor que esse tamanho, vai ocorrer overflow com seus gris items!

Para arrumar isso, será preciso colocar a declaração de `grid-template-columns` em uma media query:

[Exemplo no CodePen](https://codepen.io/anon/pen/qzvLar)

Mas, agora que estamos na área de media queries, a grid só muda quando a viewport é pequena. Não seria recomendado colocá-la dentro de um contêiner pequeno ou se entraria novamente no problema de overflow.

Felizmente, com algumas novas adições às especificações de CSS que começaram a chegar nos navegadores, é possível corrigir esse problema, permitindo que CSS Grid aproveite todo o seu potencial como uma ferramenta para **intrinsic web design**.

## Grid intrinsecamente responsiva

O exemplo anterior teve problemas porque acontecia a definição de um valor fixo como o tamanho mínimo da track.Quando o tamanho do contêiner diminuiu, os itens não diminuíram com ele e, portanto: overflow.

Mas e se fosse possível definir um tamanho mínimo que encolheria com base no tamanho do contêiner, garantindo que as tracks nunca fossem grandes demais para o contêiner?

Por sorte, é possível fazer exatamente isso com a ajuda da [função](https://developer.mozilla.org/en-US/docs/Web/CSS/min) `[min()](https://developer.mozilla.org/en-US/docs/Web/CSS/min)`:

```scss
grid-template-columns: repeat(auto-fill, minmax(min(10rem, 100%), 1fr));
```

`min()` aceita um ou mais valores e retorna o menor valor. A mágica da função é que, assim como `calc()`, os argumentos podem usar unidades diferentes, o que permite retornar valores que mudam dinamicamente com base no contexto. Neste caso, retornando a largura atual do contêiner, limitada no valor máximo de `10rem`.

`min()` é uma das 3 novas funções de comparação introduzidas como parte de [CSS Values and Units Module Level 4](https://drafts.csswg.org/css-values-4/#comp-func). Também há `max()` -- que, naturalmente, faz o inverso de min() -- e `clamp()` -- uma função de conveniência que aplica ambos um mínimo e um máximo para um único valor.

Neste exemplo, há 2 casos com os quais é preciso atenção, e `min()` resolve ambos.

Quando o contêiner é menor que `10rem`, o valor mínimo na expressão `minmax()` é definido como a largura total do contêiner, fornecendo uma bela exibição de coluna única sem overflow.

Quando o contêiner é maior que `10rem`, o valor mínimo é definido como `10rem`, que garante uma grid responsiva com tracks iguais a pelo menos `10rem` cada.

## CSS Grid intrinsecamente responsiva no mundo real

Se você está pensando "Isso parece legal e tudo mais, mas ainda não é possível usar em projetos de verdade", você tem apenas metade da razão.

`min()` não é muito bem suportado, mas está disponível em pelo menos um navegador: o Safari implementou silenciosamente `min()` e `max()` algumas versões anteriores! Infelizmente, ainda não há nada sobre `clamp()` ainda, mas é possível simulá-la usando as outras duas.

Além disso, [a Tab Atkins anunciou recentemente que o suporte ao Chrome está a caminho](https://twitter.com/tabatkins/status/1141830941628780544). Se você deseja acompanhar o suporte ao navegador, [o CanIUse possui uma página para as 3 funções](https://caniuse.com/#feat=css-math-functions).

Contadas as boas novas, aqui está uma versão funcional do código acima (abra no Safari para ver funcionando direitinho):

[Exemplo no CodePen](https://codepen.io/anon/pen/VJggRL)

Com essa falta de suporte amplo, por enquanto, é possível colocá-lo em camadas no código existente usando _progressive enhancement_. Algo mais ou menos como:

[Exemplo no CodePen](https://codepen.io/anon/pen/bPzzZr)

Aqui, usou-se `calc()` como fallback. A parte principal é o `calc(10% + 7.5rem)`, que combina um mínimo fixo com uma largura percentual. Ao calcular o mínimo com base em ambos, o limite é reduzido para disparar o overflow. Agora, ele será acionado quando o contêiner for um pouco maior que `7.5rem`, enquanto, na solução anterior, ele seria acionado a `10rem`.

Essa solução é um pouco complicada, portanto, convém ajustar a porcentagem e os valores fixos para se adequar ao design de suas próprias grids.

Com isso como alternativa, é possível tirar proveito da capacidade do CSS de substituir declarações de propriedade duplicadas, declarando novamente `grid-template-columns`. Browsers que suportam `min()` -- na data de publicação deste artigo, o Safari -- obterão a solução totalmente responsiva, enquanto Chrome, Firefox, Edge e outros receberão o fallback.

À medida que mais navegadores adicionam suporte a `min()`, eles alternam automaticamente para o novo layout.

## Conclusão

As funções `min()`, `max()` e `clamp()` são ferramentas realmente poderosas, permitindo alternar entre valores em tempo real com base nas condições de mudança.

Ser capaz de testá-los em um navegador real abre muitas oportunidades de exploração, e tudo indica que essa pequena correção para o CSS Grid está apenas arranhando a superfície das muitas maneiras pelas quais os desenvolvedores poderemos esses recursos daqui para frente.

E você, já viu algum exemplo incrível de **CSS Grid intrinsecamente responsiva** que usa `min()`, `max()` e `clamp()`?

---

Fonte: [dpw - desenvolvimento para web](https://dpw.dev/) (pt-BR).
Guia para agentes: https://dpw.dev/llms.txt
Índice completo: https://dpw.dev/sitemap-index.xml
Feed: https://dpw.dev/rss.xml
