Flexbox: Guia de Funcionamento e Propriedades

Quais Problemas o Flexbox Resolve?

Mesmo com todos os avanços trazidos pelo CSS3, alguns problemas ainda são difíceis de se resolver utilizando somente propriedades de posicionamento ou floats, disponvíveis nas especificações tradicionais do CSS.

Fazer coisas como alinhar itens verticalmente dentro de um container, posicionando um em cada extremidade, muito comum quando em um site temos de um lado a logomarca e do outro, o menu;

Ilustração de itens centralizados verticalmente dentro de seu pai através do flexbox.

Ou ainda, garantir que itens dentro de um container tenham sempre a mesma altura, independente da quantidade de conteúdo que possuem;

Ilustração de flex itens sempre com a mesma altura, independente da quantidade de conteúdo que possuem.

Também é desafiante fazer com que os filhos de um container ocupem uma quantidade igual de largura/altura disponível, independente da quantidade de largura/altura disponível.

Demandas como as citadas acima, somado à necessidade de facilitar a construção de layouts que se adaptem aos diferentes tamanhos de telas da grande variedade de dispositivos que hoje acessam a internet, fizeram surgir novas especificações de CSS, como é o caso do Flexbox e do Grid Layout.

Neste artigo, iremos tratar a respeito das especificações do Flexbox, que promete capacidades poderosas de alinhamento em diferentes tamanhos de tela.

Um dos primeiros pontos a se entender a respeito do Flexbox é o seguinte: nas especificações tradicionais do CSS3, quando utilizamos um float: right; por exemplo ou qualquer propriedade que seja, estamos controlando o elemento filho em relação ao pai ou ancestral.

Imagem com filho flutuando à direita.

Já o Flexbox, nos permite controlar os filhos a partir do pai.

Ilustração de flex container mostrando o controle do pai sobre seus filhos.

Como Ativar o Flexbox?

O flexbox é ativado em um elemento html (tag) através da propriedade display com valor flex ou inline-flex. A partir da ativação, esse elemento passa a ser chamado de flex container (caixa flexível) e todos os seus filhos diretos viram flex items (itens flexíveis).

Qual a diferença entre declarar display flex ou inline-flex?

Ao utilizar display: flex;, o elemento que tem essa propriedade e passou agora a ser chamado de flex container, tem um comportamento similar ao display: block;. Ou seja, se ele não tem uma largura definida, ocupa 100% da largura do seu pai. Se um width for definido, ele será aplicado, ainda assim, o flex container em questão não permite que outro elemento fique ao lado dele.

A ilustração abaixo, tenta demonstrar isso de uma forma visual. Nela, o container flex está delimitado com uma borda tracejada para facilitar a visualização. Se você redimensionar sua tela até que os dois containers tenham espaço para ficarem lado a lado, eles ainda continuarão um em baixo do outro, justamente pelo comportamento descrito no parágrafo anterior.

flex item
flex item maior
flex item
flex item maior

Por outro lado, se você atribuir ao elemento display: inline-flex;, vai observar um comportamento similar ao do display: inline-block;, onde será permitido que outros elementos fiquem ao lado do flex container e sua largura por padrão será definida pela largura total dos seus filhos. A altura do container será definida pela altura do maior flex item.

flex item
flex item maior
flex item
flex item maior

Como os Flex Itens se organizam dentro de um Flex Container?

Os flex itens se posicionam dentro do flex container em dois eixos, o main axis (eixo principal) que por padrão fica no eixo x (horizontal) e o cross axis (eixo transversal) que por padrão fica no eixo y (vertical).

Por padrão, todos os flex itens fluem no sentido de leitura do idioma que você definiu para o seu site. Se o idioma for português, o main axis terá seu início na extremidade esquerda do flex container, chamamos esse início de main start, e o término ficará na extremidade direita do flex container que chamamos de main end.

Agora, no cross axis, o início fica na extremidade superior do flex container, que chamamos de cross start, e o fim na extremidade inferior do flex container que chamamos de cross end.

Propriedades Aplicáveis ao Flex Container

Vamos passar a ver agora, as propriedades que alteram o comportamento desses eixos e os modos de organização dos itens flexíveis dentro de um container flex.

flex-direction

A propriedade que controla o main axis (eixo principal) é a flex-direction. Seu valor inicial é row (linha), por isso que o main axis por padão é o eixo x.

Se atribuirmos ao flex-direction o valor row-reverse, o main axis continuará sendo o eixo x, mas vamos acabar invertendo o main start e o main end, conforme ilustra a figura abaixo.

O flex-direction pode receber mais dois valores, e eles são column e column-reverse.

Se atribuirmos o valor column a essa propriedade, o main axis passará a ser o eixo y e, obviamente, o cross axis vai mudar para o eixo x, porque ele sempre corre perpendicular ao eixo principal. Isso fará com que os flex itens se disponham em coluna.

Utilizando-se column-reverse, os itens flexíveis continuarão um em baixo do outro formando uma coluna e a única coisa que mudará é a ordem deles, decorrente novamente da inversão do main start e main end.

flex-wrap

A propriedade flex-wrap define se vai haver ou não quebra de linha quando os itens de um flex container forem muito grandes para serem exibido em uma linha.

O valor inicial do flex-wrap é nowrap, ou seja, não permite quebra de linha. Essa configuração vai obrigar os filhos desse container a se alinharem todos ao longo do eixo principal.

Caso não haja espaço suficiente para que todos os flex itens caibam no eixo principal, eles irão tentar diminuir até o tamanho de seu conteúdo para caber. Quando não for mais possível diminuir e, ainda assim, não couberem todos em uma linha, irão vazar para fora do container.

Nós somos flex itens
Estamos dentro de um container com bordas tracejadas
Temos uma largura definida
Mas vamos encolher até o tamanho do conteúdo se preciso for
Se mesmo assim não coubermos, vamos vazar o container
Para que você nos veja vazar, redimencione sua tela até que não possamos mais caber no container

O outro valor possível ao flex-wrap é wrap, fazendo com que os itens flexíveis não mais encolham para caber, e sim, quebrem a linha quando forem muito grandes para serem exibidos em uma linha.

Nós continuamos sendo itens flex
Ainda estamos dentro de um container com bordas tracejadas
Continuamos com uma largura definida
Não vamos mais nos espremer em uma linha
Quando não pudermos mais ser exibidos em uma linha, vamos quebrar para a próxima.
Caso queira ver como nos comportamos, redimencione sua tela.
Temos também agora uma borda, para facilitar a visualização.

Quando a quebra é permitida, você deve considerar cada linha como um novo contêiner flexível. Qualquer distribuição de espaço ocorrerá nessa linha, sem referência às linhas anteriores ou posteriores.

A forma abreviada flex-flow

Você pode combinar as propriedades flex-direction e flex-wrap através da forma abreviada flex-flow, onde o primeiro valor especifica o flex-direction e o segundo representa o flex-wrap. Por exemplo:

flex-flow: row wrap;

justify-content

A propriedade justify-content alinha os flex itens ao longo do eixo principal.

Quando falamos do alinhamento ou definição de tamanho dos flex itens, estamos falando da forma como os espaços são distribuidos entre os itens dentro de um container flex.

Se nós temos três itens flex, cada um com 100 pixels de largura, dentro de um container de 500 pixels, então o espaço que precisamos para colocar nossos itens é de 300 pixels, sobrará ainda 200.

Quando mantemos a propriedade justify-content com seu valor inicial flex-start, fazemos com que a sobra de espaço seja depositada após o último dos flex itens, alinhando assim os itens no início do eixo principal.

Você também pode definir o valor como flex-end para que a sobra de espaço seja depositada antes do primeiro dos flex itens.

Flex item 1
Flex item 2
Flex item 3

Ou ainda center, que depositará a metade do espaço antes do conjunto de itens flex e a outra metades após. Provocando um alinhamento ao centro do eixo principal.

Flex item 1
Flex item 2
Flex item 3

Outro valor possível é o space-around, para compartilhar todo o espaço livre igualmente entre os itens e causar uma quantidade igual de espaço à direita e à esquerda de cada item.

Há ainda, o valor space-between que distribui o espaço entre os itens da mesma forma descrita no paragrafo anterior, exceto para as faces dos itens que dão de encontro com a borda do container.

Flex item 1
Flex item 2
Flex item 3

align-items

A propriedade align-items alinha os itens ao longo do eixo transversal. Seu valor inicial é stretch.

O stretch permite que os itens estiquem no sentido do eixo transversal até ficarem todos do tamanho do maior flex item, caso tenham tamanhos diferentes.

Flex item 1
Flex item 2
Flex item 3 tem texto a mais

Se o flex container tiver altura fixa no sentido do eixo transversal, os itens também irão esticar até o seu rodapé.

Flex item 1
Flex item 2
Flex item 3 tem texto a mais

Se você definir o align-items para flex-start, os itens irão se alinhar no início do eixo transversal.

Flex item 1
Flex item 2
Flex item 3 tem texto a mais

Definindo essa mesma propriedade para center, os itens se alinharão no centro do eixo transversal.

align-items: center;
Flex item 1
Flex item 2
Flex item 3 tem texto a mais

Já o flex-end, alinha os itens no final do eixo.

align-items: flex-end;
Flex item 1
Flex item 2
Flex item 3 tem texto a mais

align-content

O align-content funciona da mesma forma que o justify-content, a não ser pelo fato de que atua sobre o eixo transversal e possui uma opção extra em relação ao justify-content. Essa opção é o stretch, que também é o valor padrão da propriedade.

Propriedades Aplicadas aos Flex Itens

Para que tenhamos mais controle sobre os flex itens, podemos selecioná-los diretamente.

flex-basis

O flex-basis define o tamanho do item. Seu valor inicial é auto, nesse caso, o navegador irá olhar se o item possui uma largura definida. Em caso positivo, essa será a largura do item. Se o item não tiver uma largura definida, a largura do seu conteúdo será utilizada como flex basis.

flex-grow

Quando a propriedade flex-grow está definida como um número inteiro positivo, os flex itens podem esticar no sentido do eixo principal, a partir do seu flex basis, a fim de preencher os espaços vazios no eixo. Se mais de um item estiver autorizado a crescer, cada um ocupará uma proporção desse espaço vazio disponível.

O valor inicial do flex-grow é 0 (zero). Por isso, se você olhar nos exemplos acima, os itens não esticam ao longo do eixo principal do container.

Na ilustração abaixo, repliquei um dos exemplos anteriores permitindo que os itens crescessem.

Flex item 1
Flex item 2
Flex item 3

flex-shrink

O flex-shrink controla como o espaço será retirado dos itens quando não temos espaço suficiente no container. Se essa propriedade estiver configurada com um inteiro positivo, os itens podem ficar menores do que o seu flex-basis.

O valor inicial dessa propriedade é 1, permitindo que os itens diminuam quando for necessário. É por isso que os itens acima encolhem até o tamanho de seu conteúdo antes de vazar o container.

flex

O flex é um atalho para as três propriedades citadas acima. Ele recebe três valores. O primeiro deles é referente ao flex-grow, o segundo ao flex-shrink e o terceiro ao flex-basis.

Como valor inicial, o flex assume cada um dos valores iniciais das propriedades individuais. Portanto, 0 1 auto.

order

Como o próprio nome sugere, essa propriedade nos permite mudar a ordem visual dos elementos, sem mexer na ordem em que eles se apresentam no html.

Suponha que tenhamos a página de um artigo, composta pelo cabeçalho header com o título, a parte principal da página main onde está todo o conteúdo, e uma seção à parte aside onde encontra-se um menu geral que deve estar presente em todas as páginas deste site.

Pensando em termos de Otimização para Mecanismos de Busca (SEO) e semântica de html, o ideal é que este aside esteja no final da página. Porém, se quisermos que o menu apareça visualmente no topo, podemos lançar mão do order e dizer que o aside terá order: 1;, o header, order: 2; e o main, order: 3;, conforme ilustra o exemplo abaixo.

See the Pen RwwBPBO by airtonklauck (@airtonklauck) on CodePen.

Ir para o topo