Flexbox: Qual é o tamanho dessa caixa flexível?

Publicados: 2022-03-10
Resumo rápido ↬ Nos dois últimos artigos, vimos o que acontece quando criamos um contêiner flexível e também analisamos o alinhamento. Desta vez, exploramos a questão muitas vezes confusa de dimensionamento no Flexbox. Como a Flexbox decide quão grandes as coisas devem ser?

Esta é a terceira parte da minha série sobre Flexbox. Nos dois artigos anteriores, vimos o que acontece quando você cria um contêiner flexível e exploramos o alinhamento como ele funciona no Flexbox. Desta vez, vamos dar uma olhada no dimensionamento. Como controlamos o tamanho de nossos itens flexíveis e quais escolhas o navegador está fazendo quando controla o tamanho?

Exibição inicial de itens flexíveis

Se eu tiver um conjunto de itens, que têm comprimentos variáveis ​​de conteúdo dentro, e definir seu pai para display: flex , os itens serão exibidos como uma linha e alinhados no início desse eixo. No exemplo abaixo, meus três itens têm uma pequena quantidade de conteúdo e são capazes de exibir o conteúdo de cada item como uma linha ininterrupta. Há espaço no final do contêiner flex no qual os itens não crescem porque o valor inicial de flex-grow é 0 , não cresce .

Três itens com espaço no final
Os itens flexíveis têm espaço para serem exibidos em uma linha (visualização grande)

Se eu adicionar mais texto a esses itens, eles eventualmente preencherão o contêiner e o texto começará a ser quebrado. As caixas recebem uma parte do espaço no contêiner que corresponde à quantidade de texto em cada caixa — um item com uma sequência de texto mais longa recebe mais espaço. Isso significa que não acabamos com uma coluna alta e magra com muito texto quando o item ao lado contém apenas uma única palavra.

Três itens, o item final tem texto mais longo e o texto é quebrado
O espaço é distribuído para dar mais espaço a um item mais longo (visualização grande)

Esse comportamento provavelmente será familiar para você se você já usou o Flexbox, mas talvez você tenha se perguntado como o navegador está funcionando nesse dimensionamento, pois se você olhar em vários navegadores modernos, verá que todos fazem a mesma coisa. Isso se deve ao fato de que detalhes como esse são trabalhados na especificação, garantindo que qualquer pessoa que implemente o Flexbox em um novo navegador ou outro agente de usuário esteja ciente de como esse cálculo deve funcionar. Podemos usar a especificação para descobrir essas informações por nós mesmos.

Mais depois do salto! Continue lendo abaixo ↓

A especificação de dimensionamento intrínseco e extrínseco do CSS

Você descobre rapidamente, ao olhar para qualquer coisa sobre dimensionamento na especificação Flexbox, que muitas das informações que você precisa estão em outra especificação – CSS Intrisnic and Extrinsic Sizing. Isso ocorre porque os conceitos de dimensionamento que estamos usando não são exclusivos do Flexbox, da mesma forma que as propriedades de alinhamento não são exclusivas do Flexbox. No entanto, para saber como essas construções de dimensionamento são usadas no Flexbox, você precisa consultar as especificações do Flexbox. Pode parecer um pouco como se você estivesse pulando para frente e para trás, então vou reunir algumas definições-chave aqui, que usarei no restante do artigo.

Tamanho preferido

O tamanho preferencial de uma caixa é o tamanho definido por uma width ou height , ou os aliases lógicos para essas propriedades de inline-size e block-size . Usando:

 .box { width: 500px; }

Ou o alias lógico inline-size :

 .box { inline-size: 500px; }

Você está afirmando que deseja que sua caixa tenha 500 pixels de largura ou 500 pixels na direção em linha.

Tamanho mínimo do conteúdo

O tamanho mínimo de conteúdo é o menor tamanho que uma caixa pode ter sem causar estouro. Se sua caixa contiver texto, todas as oportunidades possíveis de quebra automática serão aproveitadas.

tamanho máximo do conteúdo

O tamanho máximo do conteúdo é o maior tamanho que a caixa pode ter para conter o conteúdo. Se a caixa contiver texto sem formatação para dividi-la, ela será exibida como uma string longa e ininterrupta.

Tamanho principal do item flexível

O tamanho principal de um item flexível é o tamanho que ele possui na dimensão principal. Se você estiver trabalhando em uma linha — em inglês — o tamanho principal é a largura. Em uma coluna em inglês, o tamanho principal é a altura.

Os itens também têm um tamanho principal mínimo e máximo, conforme definido por sua min-width min-height na dimensão principal.

Calculando o tamanho de um item flexível

Agora que temos alguns termos definidos, podemos dar uma olhada em como nossos itens flexíveis são dimensionados. O valor inicial das propriedades flex são os seguintes:

  • flex-grow: 0
  • flex-shrink: 1
  • flex-basis: auto

A flex-basis é a coisa a partir da qual o dimensionamento é calculado. Se flex-basis para 0 e flex-grow para 1, todas as nossas caixas não terão largura inicial, portanto, o espaço no contêiner flex será dividido uniformemente, atribuindo a mesma quantidade de espaço a cada item.

Veja o Pen Smashing Flexbox Series 3: flex: 1 1 0; por Rachel Andrew (@rachelandrew) no CodePen.

Veja o Pen Smashing Flexbox Series 3: flex: 1 1 0; por Rachel Andrew (@rachelandrew) no CodePen.

Considerando que se flex-basis for auto e flex-grow: 1 , apenas o espaço livre é distribuído, levando em consideração o tamanho do conteúdo.

Veja o Pen Smashing Flexbox Series 3: flex: 1 1 auto short text de Rachel Andrew (@rachelandrew) no CodePen.

Veja o Pen Smashing Flexbox Series 3: flex: 1 1 auto short text de Rachel Andrew (@rachelandrew) no CodePen.

Em situações em que não há espaço livre, por exemplo, quando temos mais conteúdo do que cabe em uma única linha, não há espaço para distribuir.

Veja o Pen Smashing Flexbox Series 3: flex: 1 1 auto long text de Rachel Andrew (@rachelandrew) no CodePen.

Veja o Pen Smashing Flexbox Series 3: flex: 1 1 auto long text de Rachel Andrew (@rachelandrew) no CodePen.

Isso nos mostra que descobrir o que significa auto é muito importante se quisermos saber como o Flexbox calcula o tamanho de nossas caixas. O valor de auto será nosso ponto de partida.

Definindo Automático

Quando auto é definido como um valor para algo em CSS, ele terá um significado muito específico nesse contexto, que vale a pena dar uma olhada. O CSS Working Group gasta muito tempo descobrindo o que auto significa em qualquer contexto, como explica esta palestra para o editor de especificações Fantasai.

Podemos encontrar as informações sobre o significado de auto quando usado como flex-basis na especificação. Os termos definidos acima devem nos ajudar a dissecar essa afirmação.

“Quando especificado em um item flex, a palavra-chave auto recupera o valor da propriedade main size como o `flex-basis` usado. Se esse valor for auto, então o valor usado é `content`.”

Então, se nosso flex-basis for auto , o Flexbox dará uma olhada na propriedade main size definida. Teríamos um tamanho principal se tivéssemos dado a qualquer um de nossos itens flexíveis uma width . No exemplo abaixo, todos os itens têm uma largura de 110px, então isso está sendo usado como o tamanho principal, pois o valor inicial para flex-basis é auto.

Veja Pen Smashing Flexbox Series 3: flex items with a width por Rachel Andrew (@rachelandrew) no CodePen.

Veja Pen Smashing Flexbox Series 3: flex items with a width por Rachel Andrew (@rachelandrew) no CodePen.

No entanto, nosso exemplo inicial tem itens que não têm largura, isso significa que seu tamanho principal é auto e, portanto, precisamos passar para a próxima frase, “Se esse valor for auto, então o valor usado é content ”.

Agora precisamos ver o que a especificação diz sobre a palavra-chave de content . Este é outro valor que você pode usar (em navegadores compatíveis) para seu flex-basis , por exemplo:

 .item { flex: 1 1 content; }

A especificação define o content da seguinte forma:

“Indica um tamanho automático baseado no conteúdo do item flexível. (Geralmente é equivalente ao tamanho máximo do conteúdo, mas com ajustes para lidar com proporções, restrições de tamanho intrínsecas e fluxos ortogonais”

Em nosso exemplo, com itens flexíveis que contêm texto, podemos ignorar alguns dos ajustes mais complicados e tratar o content como sendo o tamanho máximo do conteúdo.

Então isso explica porque, quando temos uma pequena quantidade de texto em cada item, o texto não quebra. Os itens flexíveis são dimensionados automaticamente, então o Flexbox está olhando para o tamanho máximo do conteúdo, os itens cabem em seu contêiner nesse tamanho e o trabalho está feito!

A história não termina aqui, pois quando adicionamos mais conteúdo as caixas não ficam no tamanho máximo de conteúdo. Se o fizessem, eles sairiam do contêiner flexível e causariam estouro. Uma vez que eles enchem o contêiner, o conteúdo começa a se envolver e os itens se tornam tamanhos diferentes com base no conteúdo dentro deles.

Resolvendo Comprimentos Flexíveis

É neste ponto que a especificação se torna razoavelmente complexa, no entanto, as etapas que precisam acontecer são as seguintes:

Primeiro, some o tamanho principal de todos os itens e veja se é maior ou menor que o espaço disponível no container.

Se o tamanho do container for maior que o total, vamos nos preocupar com o fator flex-grow , pois temos espaço para crescer.

itens flexíveis com espaço livre no final
No primeiro caso, nossos itens têm espaço disponível para crescer. (Visualização grande)

Se o tamanho do contêiner for menor que o total, vamos nos preocupar com o fator flex-shrink , pois precisamos encolher.

itens flexíveis transbordando o contêiner
No segundo caso, nossos itens são muito grandes e precisam encolher para caber no contêiner. (Visualização grande)

Congele todos os itens inflexíveis, o que significa que já podemos decidir o tamanho de alguns itens. Se estivermos usando flex-grow , isso inclui todos os itens que possuem flex-grow: 0 . Este é o cenário que temos quando nossos flex items têm espaço sobrando no container. O valor inicial de flex-grow é 0, então eles ficam tão grandes quanto sua largura máxima e então eles não crescem mais em relação ao tamanho principal.

Se estivermos usando flex-shrink , isso inclui todos os itens com flex-shrink: 0 . Podemos ver o que acontece nesta etapa se dermos ao nosso conjunto de itens flexíveis um fator flex-shrink de 0. Os itens ficam congelados em seu estado max-content e, portanto, não se flexionam e se organizam para caber no contêiner.

Veja Pen Smashing Flexbox Series 3: flex: 0 0 auto por Rachel Andrew (@rachelandrew) no CodePen.

Veja Pen Smashing Flexbox Series 3: flex: 0 0 auto por Rachel Andrew (@rachelandrew) no CodePen.

No nosso caso — com os valores iniciais de itens flexíveis — nossos itens podem encolher. Assim, as etapas continuam e o algoritmo entra em um loop no qual calcula quanto espaço atribuir ou remover. No nosso caso, estamos usando flex-shrink , pois o tamanho total de nossos itens é maior que o contêiner, então precisamos tirar espaço.

O fator flex-shrink é multiplicado pelo tamanho da base interna dos itens , no nosso caso, esse é o tamanho max-content . Isso dá um valor com o qual reduzir o espaço. Se os itens removessem o espaço apenas de acordo com o fator flex-shrink , os itens pequenos poderiam essencialmente desaparecer, tendo todo o seu espaço removido, enquanto o item maior ainda teria espaço para encolher.

Há uma etapa adicional neste loop para verificar itens que se tornariam menores ou maiores do que o tamanho principal de destino, caso em que o item para de crescer ou encolher. Novamente, isso é para evitar que certos itens se tornem pequenos ou enormes em comparação com o restante dos itens.

Tudo isso foi simplificado em termos de especificações, já que não analisei alguns dos cenários mais extremos, e geralmente você pode simplesmente ir mais longe em sua mente, supondo que esteja feliz em deixar o Flexbox fazer o que quer e não está atrás de pixel perfeição. Lembrar os dois fatos a seguir funcionará na maioria dos casos.

Se você estiver crescendo de auto , a flex-basis será tratada como qualquer largura ou altura no item ou o tamanho max-content . O espaço será então atribuído de acordo com o fator flex-grow usando esse tamanho como ponto de partida.

Se você estiver encolhendo de auto , a flex-basis será tratada como qualquer largura ou altura no item ou o tamanho max-content . O espaço será então removido de acordo com o tamanho do flex-basis multiplicado pelo fator flex-shrink e, portanto, removido em proporção ao tamanho máximo do conteúdo dos itens.

Controlando o crescimento e o encolhimento

Passei a maior parte deste artigo descrevendo o que o Flexbox faz quando deixado em seus próprios dispositivos. Você pode, é claro, exercer maior controle sobre seus itens flexíveis usando as propriedades flex . Esperamos que pareçam mais previsíveis com uma compreensão do que está acontecendo nos bastidores.

Ao definir seu próprio flex-basis , ou dar ao próprio item um tamanho que é então usado como flex-basis você recupera o controle do algoritmo, informando ao Flexbox que deseja aumentar ou diminuir desse tamanho específico. Você pode desativar o crescimento ou a redução completamente definindo flex-grow ou flex-shrink como 0. Nesse ponto, no entanto, vale a pena usar o desejo de controlar itens flexíveis como um momento para verificar se você está usando o método de layout correto. Se você estiver tentando alinhar itens flexíveis em duas dimensões, talvez seja melhor escolher Layout de grade.

Problemas relacionados ao tamanho da depuração

Se seus itens flexíveis estão terminando em um tamanho inesperado, isso geralmente ocorre porque sua base flexível é automática e há algo dando a esse item uma largura, que está sendo usada como base flexível. Inspecionar o item no DevTools pode ajudar a identificar de onde vem o tamanho. Você também pode tentar definir uma flex-basis de 0 que forçará o Flexbox a tratar o item como tendo largura zero. Mesmo que esse não seja o resultado que você deseja, ajudará a identificar o valor flex-basis em uso como sendo o culpado por seus problemas de dimensionamento.

Espaços Flexíveis

Um recurso muito solicitado do Flexbox é a capacidade de especificar lacunas ou medianizes entre itens flexíveis da mesma forma que podemos especificar lacunas no layout de grade e no layout de várias colunas. Esse recurso é especificado para o Flexbox como parte do Box Alignment, e a primeira implementação do navegador está a caminho. O Firefox espera enviar as propriedades de intervalo para Flexbox no Firefox 63. O exemplo a seguir pode ser visualizado no Firefox Nightly.

Veja Pen Smashing Flexbox Series 3: flex-gaps por Rachel Andrew (@rachelandrew) no CodePen.

Veja Pen Smashing Flexbox Series 3: flex-gaps por Rachel Andrew (@rachelandrew) no CodePen.
Três linhas de itens com espaçamento entre elas
A imagem como vista no Firefox 63 (visualização grande)

Assim como no layout da grade, o comprimento da folga é levado em consideração antes que o espaço seja distribuído para os itens flexíveis.

Empacotando

Neste artigo, tentei explicar alguns dos pontos mais sutis de como o Flexbox determina o tamanho dos itens flexíveis. Pode parecer um pouco acadêmico, no entanto, levar algum tempo para entender como isso funciona pode economizar muito tempo ao usar o Flexbox em seus layouts. Acho muito útil voltar ao fato de que, por padrão, o Flexbox está tentando fornecer o layout mais sensato de um monte de itens com tamanhos variados. Se um item tiver mais conteúdo, ele receberá mais espaço. Se você e seu design não concordarem com o que a Flexbox acha que é melhor, então você pode retomar o controle configurando sua própria flex-basis .