Além das unidades CSS - intrinsic sizing e responsividade
Tags: css, braziliandevs
Published: 2023-04-30 17:20:17

_Vocês sabem o que são tamanhos intrínsecos no CSS?
Esse artigo pretende explicar como funcionam os valores intrínsecos de max-content, min-content, fit-content e auto. Entender essas propriedades me fez tomar decisões de layout mais informadas, tendo um controle refinado sobre meu conteúdo e criando layouts mais robustos._

## Sobre "valor intrínseco"

_Intrinisic sizing_ se refere ao valor de `width` ou `height` do componente sendo calculado à partir dos valores do conteúdo e não de fatores externos como unidades estáticas como px ou relativas como % do pai imediato ou unidades de viewport.

Mas e quando queremos que o tamanho do container não seja relativo à unidades externas como viewport ou o container pai, e também não seja fixa como `px` ou `pt`?

Vamos pensar no caso de um botão, por exemplo. Esse botão receberá texto ou texto + ícone, ele terá apenas uma linha, nunca podendo "quebrar" o conteúdo pra linha de baixo. Quando esse botão tem espaço o suficiente em um container, nem precisamos declarar `width`, pois o valor padrão de `width` é `auto`, o que significa que a largura do elemento vai ser **igual a soma de sua margin-inline, padding-inline, border-inline e conteúdo**<a href="#inline">¹</a>.

![Demonstração do valor auto sendo inferido na propriedade width](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2etdal8u5oi3ona5hkgs.png)

&nbsp;

O problema é quando diminuímos o tamanho do container pai - o container tenta "espremer" ou quebrar o conteúdo de linha pra que esse conteúdo não vaze (overflow).

![Conteúdo do botão sofrendo overflow quando o container do botão é menor que o mesmo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ywc6dztfnmurgh0eap6m.png)

&nbsp;

Como esse não é o comportamento esperado, podemos testar algumas soluções como `overflow: hidden;`, que esconde o conteúdo vazado, somado ao `text-overflow: ellipsis;` que faz com que o texto oculto pelo `overflow` ganhe reticências. Porém por mais que essas soluções assegurem a estabilidade do layout, perdemos **legibilidade**.

![4 botões, um com texto, outro com um ícone, o terceiro com texto escondido por overflow e o quarto com overflow ellipsis](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k79hl3ewqztz3zb5iq7a.png)

&nbsp;

Percebe que pra esse layout funcionar, precisamos ter controle sobre como o container (nesse caso o botão) se comporta em relação ao seu conteúdo, não em relação ao seu pai?

<br />

-------

<br />

## min-content
O `min-content` define o menor tamanho que um elemento pode ter sem ter overflow. Ele identifica a largura do maior filho desse container e quebra de linha todos os elementos que não cabem juntos nessa largura.

![Exemplo de min-content com um texto quebrando sempre pra linha de ](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gim85th308kppou26es2.png)
<small>No caso acima, o maior filho era o TextNode com a palavra "corridor". Tudo o que não cabia na largura de "corridor" foi quebrado pra linha de baixo.</small>

&nbsp;

Um caso de uso incrível é demonstrado nesse tweet do Stefan Judis.
{% twitter 1329345425640464384 %}

<br />

-------

<br />

## max-content
O valor de `max-content` por exemplo faz com que o elemento sempre seja do tamanho do conteúdo, independente se ele tem espaço pra isso ou não.

No caso abaixo, o texto em roxo está com `max-content`, mesmo o container tendo uma width fixa, o tamanho do texto é respeitado, causando overflow.

![Exemplo de container sendo transbordado por um texto com max-content](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rnsu8mytqubsxk93vsba.png)

&nbsp;

Isso resolveria o problema do botão, por exemplo, pois nesse caso de uso a legibilidade do conteúdo sem quebra de linha era mais importante do as restrições de layout que isso causaria pro container pai desse elemento. Para evitar problemas com overflow nesse caso, é necessário que o pai de um elemento `max-content` tenha alguma lógica de quebra automática de conteúdo, como a propriedade `flex-wrap: wrap;`, por exemplo.


<br />

-------

<br />

## fit-content

Já o `fit-content` é um valor mais razoável - ele segue a seguinte lógica:

**SE** espaço disponível  < max-content
Usa o espaço disponível

**SE** espaço disponível < min-content
Usa o `min-content`.

Em outras palavras, usa espaço disponível, nunca menor que o `min-content`, nunca maior que o `max-content`.


![Demonstração de um texto com fit-content cabendo perfeitamente dentro do seu container](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ei33z6l4d9y1wn7gtnf.png)


Outra forma de expressar o `fit-content` é na sintaxe de função. Atual

```css
.container {
  // sintaxe ainda não aprovada pra width
  width: fit-content(200px);

  // mas já funciona com CSS grid
  grid-template-columns: fit-content(100%) 1fr;
  
}
```

O cálculo do fit-content nesse caso funcionaria da seguinte forma se representado de forma hipotética pelo Javascript. Os valores de tamanho máximo e mínimo são calculados pelo próprio box model, portanto podemos fingir que eles estão disponíveis na _closure_ da função pra esse exemplo.

```js
function fitContent(arg) {
  return Math.min(
    maxSize,
    Math.max(minSize, arg)
  )
}

```
A sintaxe de função só tá disponível pra uso dentro do contexto do CSS grid, mas já tá disponível pra outras propriedades [no rascunho do Box Model Module 4](https://w3c.github.io/csswg-drafts/css-sizing-4), junto com a propriedade `stretch`.

<br />

-------

<br />

## Então basta eu usar fit-content pra tudo, né?

> Na verdade não.

É sempre bom entender como essas propriedades funcionam e definir seus tamanhos de acordo com suas necessidades. Nos exemplos abaixo, `fit-content` e `auto` parecem que dão no mesmo resultado:

| Com o valor `auto` | Com o valor `fit-content` |
| --- | --- |
| ![bloco de texto com valor de width de auto](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xhjt37o1cczoc1e2thux.png) | ![Bloco de texto com o valor de width de fit-content](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i8bv2dj9ygltmxbh5l3k.png) |

&nbsp;


Agora, se eu diminuo o tamanho do texto, o `fit-content` (à esquerda) faz com que o container do texto seja exatamente igual ao conteúdo do texto, já o `auto` (à direita) faz com que o conteúdo ocupe a largura disponível, como se fosse um `stretch`

| Com o valor `auto` | Com o valor `fit-content` |
| --- | --- |
| ![bloco de texto com valor de width de auto](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/17r73n5g1tvw95eoi5kv.png) | ![Bloco de texto com o valor de width de fit-content](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1pc1f819l2lzlqutrwc2.png) |

<br />

-------

<br />

## Suporte

As unidades de tamanho intrínseco com atual suporte são `max-content`, `min-content` e `fit-content`, mas há um rascunho da W3C pra aprovação do valor `stretch`.

Esses valores chegaram no CSS Box-Sizing Module 3 e tem suporte amplo em todos navegadores modernos, porém com algumas restrições!

![Print do site caniuse na pesquisa pra intrinsic-sizes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3ildfqpocqxzkhvfqoum.png)
<small>A porcentagem de uso sem prefixing ainda é muito boa, 95.39%. Em <time>30/04/2023</time></small>

Caso a regra não tenha suporte de navegador, ele mesmo vai usar o valor _default_, no caso de `height` e `width` é `auto`.
Caso você queira outro comportamento que não `auto` na ausência de suporte pra propriedades intrínsecas, pode usar uma [support rule.](https://developer.mozilla.org/en-US/docs/Web/CSS/@supports).

```css
@supports not (width: fit-content) {
 width: auto;
}

```

<br />

-------

<br />



> <span id="inline">¹</span> A palavra `inline` é uma _logical property _se refere ao eixo x, ou seja `left` e `right`. Declarar dessa forma faz com que os lados esquerdo e direito permaneçam os mesmos inclusive quando o eixo de escrita for rotacionado ou invertido, como é o caso de algumas línguas asiáticas ou árabes. Mais informações [nesse artigo do Tárcio Zemel sobre logical properties](https://desenvolvimentoparaweb.com/css/css-logical-properties/)