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¹.
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).
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.
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.
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.
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
.
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 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.
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, 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
|
---|---|
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
|
---|---|
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!
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;
}
¹ A palavra
inline
é uma _logical property _se refere ao eixo x, ou sejaleft
eright
. 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
Top comments (1)
Só agora vi a referência ao artigo. Muito obrigado pela lembrança! :)