Antes de explicar em detalhes sobre o hack flex-grow 9999, faz-se interessante descrever resumidamente o que ele faz: o hack flex-grow 9999 faz um flex item se comportar como se tivesse dois valores de crescimento (flex-grow
) flexíveis. Ele impede que um flex item em uma linha cresça, permitindo este crescimento somente se estiver em sua própria linha. Tudo sem o uso de media queries.
A princípio, isso não faz o menor sentido, certo? Continue lendo e veja o exemplo para as coisas ficarem mais claras.
Imagine um flex container (display: flex
) com 2 flex items em uma linha (flex-direction: row
): Item A à esquerda e Item B à direita. O Item A não pode crescer, então aplica-se um valor 0
para flex-grow
(o valor padrão); o Item B precisa ocupar todo o espaço restante no contêiner — que pode ser alcançado com flex-grow: 1
.
A intenção é que os flex items fiquem empilhados (stacked) uns sobre os outros quando necessário. O Item B precisa pular para a segunda linha se não houver espaço suficiente para que ele tenha, por exemplo, pelo menos 20em
de largura. Adicionar flex-wrap: wrap
para o container e flex-base: 20em
para o Item B faz chegar no resultado pretendido.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
.container { display: flex; flex-direction: row; flex-wrap: wrap; } .item-a { flex-grow: 0; } .item-b { flex-basis: 20em; flex-grow: 1; } |
Agora vem a parte complicada. O Item A deve ser estendido para toda a largura do contêiner somente se os itens estiverem envolvidos (wrapped) em várias linhas. Seria possível usar media queries para atualizar o valor de flex-grow
, mas, no caso, pode ser difícil definir exatamente o breakpoint.
As razões pelas quais o breakpoint pode ser difícil de definir são:
- A largura do Item A é desconhecida — por exemplo, contém palavras que são mais longas e/ou em outro idioma
- Não se sabe a largura do elemento-pai dos componentes — pode se for usado em uma sidebar ou qualquer outro lugar
A ideia é conseguir chegar ao resultado pretendido sem usar media queries, atualizando o valor de flex-grow
do Item A para 1. O problema agora é que o Item A também crescerá se ambos os itens estiverem próximos um do outro. Para corrigir isso, é possível atribuir um valor de crescimento flexível ridiculamente grande, como 9999
— daí “hack flex-grow 9999” :-) –, ao Item B.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
.container { display: flex; flex-direction: row; flex-wrap: wrap; } .item-a { flex-grow: 1; } .item-b { flex-basis: 20em; flex-grow: 9999; } |
E eis que o resultado pretendido é alcançado:
Mas, afinal, por que e como o hack flex-grow 9999 funciona?! Flex grow define quanto do espaço livre restante um item flexível recebe. Por exemplo, se houver 100px
de espaço livre, é possível atribuir ao Item A 1/4 (25px
) do espaço restante (flex-grow: 1
) e ao Item B 3/4 (75px
) do espaço restante (flex-grow: 3
).
No caso em questão, o Item A recebe 1/10000 do espaço restante, o que resulta em 0px
(1/10000 * 100 = 0,01). Eventualmente, se houver espaço suficiente, o Item A receberá alguns pixels — mas é preciso um espaço disponível muito grande para que isso aconteça.
Conclusão sobre o hack flex-grow 9999
Apesar de Flexbox já estar “no mercado” há algum tempo, ele tem suas peculiaridades e (o que é muito comum) determinados usos e macetes vão sendo descobertos pela comunidade com seu tempo de uso. É o caso do hack flex-grow 9999.
Como flex-grow
funciona pode ser bastante confuso no começo, mas depois de entendido e dominado seu conceito, os proveitos que se tiram daí fazem valer a pena.