Além das unidades CSS - intrinsic sizing e responsividade

lixeletto

Camilo Micheletto

Posted on April 30, 2023

Além das unidades CSS - intrinsic sizing e responsividade

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¹.

Demonstração do valor auto sendo inferido na propriedade width

 

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

 

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

 

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?


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
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.

 

Um caso de uso incrível é demonstrado nesse tweet do Stefan Judis.


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

 

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.


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

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

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

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

}
Enter fullscreen mode Exit fullscreen mode

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.

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

Enter fullscreen mode Exit fullscreen mode

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, junto com a propriedade stretch.


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 Bloco de texto com o valor de width de fit-content

 

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 Bloco de texto com o valor de width de fit-content

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
A porcentagem de uso sem prefixing ainda é muito boa, 95.39%. Em

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..

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

Enter fullscreen mode Exit fullscreen mode

¹ 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

💖 💪 🙅 🚩
lixeletto
Camilo Micheletto

Posted on April 30, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related