Guia completo de Flexbox - display: flex

O Flexbox é um dos módulos do CSS criados para facilitar a vida de quem precisa criar layouts na web. Com ele é possível controlar o tamanho, alinhamento e distribuição de um contêiner e seus elementos-filhos (chamados de itens). Esse conjunto de ferramentas torna o Flexbox extremamente capaz de resolver problemas de layout em uma dimensão.

Antes do Flexbox era bastante comum ouvir uma história de alguém que não conseguiu centralizar um elemento com CSS, já que as ferramentas de layout padrão (block e inline) não lidam muito bem com o alinhamento e distribuição de elementos. Outro problema bastante comum era não conseguir facilmente tornar o tamanho de um elemento flexível, já que a única forma de fazer isso era usando unidades em porcentagem e fazendo cálculos manuais com elas.

Este post de introdução vai te mostrar os principais conceitos por trás desse poderoso módulo do CSS e como utilizá-lo para estilizar seus projetos na web. Vamos começar criando um contêiner flex.

Índice

Criando um contêiner flex

Para criar um contêiner flex, você precisa apenas utilizar display: flex em um elemento.

.elemento {
  display: flex;
}

Ao aplicar a regra display: flex, o elemento se tornará um contêiner flex e seus elementos-filhos serão do tipo flex. Do lado de fora, um contêiner flex não é diferente de um outro elemento block, mas o comportamento de seus elementos-filhos é completamente modificado.

Dica: Isso pode ser explicado na especificação Display Module Level 3, que diz que a propriedade display especifica dois tipos de display: o externo e o interno. Usar display: flex é, então, a forma curta de display: block flex, que define o display do contêiner em si como block e de seus elementos-filhos como flex.

Alinhando elementos com Flexbox

A partir do momento que você tem um contêiner flex, seus elementos serão dispostos ao longo do eixo principal, formando uma linha. Usando a propriedade flex-direction, podemos trocar a direção do eixo principal com flex-direction: column, onde o elementos formarão uma coluna. O padrão para esta propriedade é flex-direction: row.

.container-row {
  display: flex;
  flex-direction: row; /* o eixo principal será uma linha */
}

.container-column {
  display: flex;
  flex-direction: column; /* o eixo principal será uma coluna */
}

Conteiner flex e seus
eixos

A propriedade flex-direction recebe também valores que inverterão a ordem de disposição dos elementos de um contêiner flex: row-reverse e column-reverse.

flex-direction com valores row, row-reversed, column e column-reversed

Para alinhar os elementos ao longo dos dois eixos, utilizamos três propriedades de alinhamento: justify-content, align-items e align-content.

Usando a propriedade justify-content

A propriedade justify-content define o alinhamento do conteúdo do contêiner flex ao longo de seu eixo principal. Cada um de seus possíveis valores afetará o alinhamento de todo o conteúdo, resolvendo o antigo problema de centralizar elementos ou distribuí-los de forma igual.

Seu valor padrão é flex-start, que define que o conteúdo será alinhado a partir do começo do eixo principal.

Ilustração com exemplo de justify-content: flex-start

O valor flex-end define que o conteúdo será alinhado a partir do final do eixo principal.

Ilustração com exemplo de justify-content flex-end

Usando center, o conteúdo será alinhado ao centro do eixo principal.

Ilustração com exemplo de justify-content center

Um outro valor bastante útil é o space-between, que alinha o conteúdo ao longo do eixo principal e adiciona um espaço padrão entre todos os elementos.

Ilustração com exemplo de justify-content space-between

Já o space-around adiciona um espaço ao redor de todos os elementos.

Ilustração com exemplo de justify-content space-around

Parecido com o space-around, o space-evenly adiciona um espaço ao redor de todos os elementos de forma igual, incluindo os das pontas.

Ilustração com exemplo de justify-content space-evenly

Existem também outros valores para justify-content que não cobriremos neste artigo: start, end, left e right.

Alinhando elementos com a propriedade align-items

Para alinharmos elementos ao longo do eixo transversal de um contêiner flex, usamos a propriedade align-items. Os seus valores principais são: stretch, flex-start, flex-end, center, e baseline.

stretch é o valor padrão para align-items. Traduzindo para português, ”stretch” significa “esticar”. Então, por padrão, os elementos serão esticados para ocupar todo o espaço disponível no eixo transversal. Isso é muito útil quando queremos que todos os elementos tenham o mesmo tamanho quando o conteúdo interno deles é diferente.

Ilustração com exemplo de align-items stretch

Com flex-start, todos os elementos do contêiner flex se alinharão a partir do início do eixo transversal.

Ilustração com exemplo de align-items flex-start

Já o flex-end definirá que os elementos se alinhem a partir do final do eixo transversal.

Ilustração com exemplo de align-items flex-end

Usando o valor center, todos os elementos serão alinhados a partir do centro do eixo transversal.

Ilustração com exemplo de align-items center

O valor baseline distribuirá os elementos de certa forma que seus baselines se alinhem ao longo do eixo transversal.

Ilustração com exemplo de align-items baseline

Neste artigo não cobriremos alguns dos outros valores possíveis para align-items como: start, self-start, end, self-end, e os modificadores safe e unsafe.

Alinhando o conteúdo no Flexbox com align-content

Ao invés de alinhar os elementos, é possível também alinhar todo o conteúdo de um contêiner flex no eixo transversal. A propriedade align-content é menos utilizada que a align-items, mas muito útil em situações em que o contêiner flex tem um tamanho pré-definido (100vh por exemplo) e não sabemos com antecedência o tamanho de todos os elementos-filhos.

O valor padrão para esta propriedade é normal, que funciona como se nenhum valor tivesse sido definido.

Com flex-start, o conteúdo será alinhado ao início do eixo transversal. Já flex-end alinhará o conteúdo do contêiner flex ao final. Usando center, o conteúdo será alinhado ao centro.

Ilustração com exemplo de align-content flex-start, flex-end e center

Também podemos utilizar o valor space-between para adicionar espaçamento entre as linhas de conteúdo, space-around para espaçamento ao redor destas linhas e space-evenly para espaçamento igual ao redor das linhas de conteúdo incluindo as pontas.

Ilustração com exemplo de align-content space-between, space-around e space-evenly

O valor stretch fará com que as linhas de conteúdo se estiquem para tomar todo o espaço disponível no eixo transversal.

Ilustração com exemplo de align-content stretch

Neste artigo não cobriremos alguns dos outros valores possíveis para align-content como: start, end e os modificadores safe e unsafe.

Usando align-self para alinhar elementos dentro de um contêiner flex

Podemos também utilizar align-self em elementos flex para alterar seu alinhamento no eixo transversal de forma independente.

Ilustração com exemplo de align-self

A propriedade align-self recebe os mesmos valores que align-items ou align-content.

Quebrando o conteúdo em novas linhas ou colunas

Por padrão, os elementos-filhos de um contêiner flex serão dispostos ao longo dos eixos, sem quebrarem em novas linhas e colunas. Para controlar este comportamento, podemos utilizar a propriedade flex-wrap.

O valor padrão para esta propriedade é nowrap, que define que os elementos serão dispostos em uma única linha.

wrap definirá que os elementos irão ocupar novas linhas, em direção ao fim do eixo transversal.

Já o valor wrap-reverse especifica que os elementos irão ocupar novas linhas em direção ao início do eixo transversal

Ilustração com exemplo de flex-wrap

Definindo tamanhos flexíveis para os elementos flex

Além de ferramentas para distribuir e alinhar elementos-filhos em um contêiner flex, o Flexbox também tem propriedades para auxiliar na definição do tamanho de elementos. Assim como o nome deixa a entender, o forte dessas propriedades é poder escolher valores flexíveis. Com flex-grow, flex-shrink e flex-basis aplicados a um elemento-filho flex, podemos controlar o seu tamanho dentro um contêiner flex e como ele lida com a sobra ou falta de espaço.

A propriedade flex-grow

A propriedade flex-grow recebe como valor um número que represente o “fator de crescimento”. Esse número define como o elemento-filho reagirá à sobra de espaço em um contêiner flex. A sobra de espaço é calculada pelo o tamanho total do contêiner flex menos o espaço base total ocupado pelos elementos-filhos. Por padrão, o valor de flex-grow é 0.

Para entender um pouco melhor como essa propriedade funciona na prática, vamos utilizar um exemplo. Em um contêiner flex com 300px de tamanho, temos três elementos-filhos com 100px de tamanho. Os dois primeiros têm o valor de flex-grow: 1 e o terceiro tem o valor de flex-grow: 2. Nesse exemplo, teríamos uma sobra de espaço de 200px que seria distribuída entre os três elementos-filhos de acordo com os seus fatores, de forma que no final o espaço ocupado por eles seja igual ao tamanho do contêiner. Já que o terceiro elemento tem um fator de crescimento 2, e os dois primeiros têm um fator de crescimento 1, o terceiro elemento crescerá duas vezes mais do que os outros dois.

Ilustração com exemplo de flex-grow

A propriedade flex-shrink

Assim como podemos tornar flexível o crescimento dos elementos-filhos, podemos também utilizar flex-shrink para definir os seus fatores de encolhimento.

Quando faltar espaço em um contêiner flex, os seus elementos-filhos são encolhidos de acordo com o fator de encolhimento. Por padrão, o valor de flex-shrink é 1.

Ilustração com exemplo de flex-shrink

Controlando o tamanho de elementos com flex-basis

O tamanho dos elementos em um contêiner flex é calculado também de forma flexível. Por padrão, esse tamanho é calculado de acordo com o tamanho do conteúdo do elemento ou pelo seu width ou height. Esse valor padrão ajuda a pessoa desenvolvedora a criar interfaces que se adaptam ao tamanho do conteúdo, mas pode ser um tanto confuso para quem não espera esse comportamento

Ilustração com exemplo de flex-basis auto

A propriedade flex-basis pode ser alterada de seu valor padrão auto para qualquer unidade de medida de tamanho e porcentagem. Se o elemento tiver width ou height definidos e um flex-basis for definido, o valor de flex-basis tomará precedência no cálculo do tamanho base de um elemento flex.

Ilustração com exemplo de flex-basis com valores numéricos

Ordenando elementos-filhos de um contêiner flex

Outra propriedade que o Flexbox adicionou ao CSS foi a order, que controla a ordem dos elementos-filhos em um contêiner flex. Elementos em um contêiner serão ordenados de forma ascendente baseados no valor de order e sua posição no DOM.

O valor padrão de order é 0. Você pode definir order com qualquer número inteiro.

Ilustração com exemplo de order

Vale alertar que a ordenação através de valores order não altera a ordenação desses elementos no DOM, o que cria uma diferença na ordem real dos elementos e sua ordem de exibição. Isso é um problema no uso da navegação por teclado, mas um problema ainda maior para usuários de softwares de leitura de tela. Evite utilizar order se a ordenação tiver efeitos hierárquicos que prejudicariam a acessibilidade do seu site.

Suporte em diferentes navegadores

O Flexbox é suportado por grande parte dos navegadores. Mesmo assim, alguns bugs podem quebrar ou mudar o comportamento dos seus elementos de um navegador para outro. O projeto flexbugs possui uma lista de mais de 10 bugs, com dicas de como contorná-los.

Fora estes bugs, você pode esperar que o seu site estilizado com Flexbox seja renderizado corretamente em todos os navegadores mais utilizados do mercado. O site Can I Use lista o módulo CSS de Flexbox como sendo suportado nos navegadores de mais de 97% dos usuários no mundo.

Continue aprendendo

Todas essas ferramentas do módulo CSS Flexbox trouxeram uma quantidade enorme de controle e flexibilidade para estilizar componentes e layouts com CSS. Em breve escreveremos um outro post com exemplos práticos utilizando todas as propriedades que cobrimos nesta introdução. Por enquanto, você pode dar uma olhada no Solved by Flexbox para ver como o Flexbox resolve problemas clássicos de layout ou então jogar o Flexbox Froggy para aprender na prática.

Para escrever este post eu utilizei diversas referências, incluindo a especificação da W3. Para continuar aprendendo sobre Flexbox, recomendo:

Obrigado Jonathan Zanella por toda a ajuda na revisão e edição deste post.