CSS Flexbox: O que é e como funciona? O guia CSS Flexbox!

Se você já se aventurou no mundo de desenvolvimento de sites em CSS, provavelmente já ouviu falar das propriedades float e position. Por muito tempo elas foram muito utilizadas para criação de layouts na web. No entanto, por causa das dificuldades de criação de telas flexíveis e responsivas, foi arquitetado uma nova ferramenta para resolver esse tipo de problema, o CSS Flexbox.

Mesmo dominando toda a web, ainda é muito difícil lidar com o Flexbox. Um dos principais motivos seria a compatibilidade dos navegadores de entender a mecânica do Flexbox, algo muito parecido com o que acontece com o Javascript. Felizmente, nos últimos anos, a compatibilidade tem se tornado bem alta.

Hoje em dia, é inconcebível não conhecer o Flexbox, por isso esse artigo está sendo escrito para mostrar a você o conceito por trás da palavra Flex, apresentar as suas principais propriedades e exibir alguns exemplos na prática. Continue lendo!

O que é e para que serve a ferramenta CSS Flexbox?

O CSS Flexbox tem o objetivo de ajudar o desenvolvedor ou desenvolvedora a criar robustos e flexíveis layouts. Com o Flex container, temos a estrutura unidimensional e, com o Flex item, temos a unidade que se adequa dentro do sistema. Dessa forma, tem-se definido para ele os eixos principal e transversal, onde conseguimos realizar alinhamentos diversos, reajustes no tamanho dos itens, reorganização dos filhos e muito mais!

Exemplo de container CSS Flexbox

Se você já utilizou alguma vez as propriedades float ou position, já deve ter tido muitos problemas na hora de padronizar os elementos e a responsividade da tela. A partir desse problema, foi idealizado o que viria a ser então o Flexbox, isso no ano de 2009. Já em 2012, começaram a liberar a estrutura na grande parte dos navegadores modernos. Atualmente, todo browser praticamente tem amplo suporte a essa ferramenta.

Quais as diferenças entre CSS Flexbox e CSS Grid?

As duas propriedades são amplamente utilizadas no mundo web e podem ser utilizadas para complemento de cada uma. No texto a seguir, veremos as suas principais diferenças!

Flexbox

Exemplo CSS Flexbox

No Flexbox, temos um sistema unidimensional em que podemos criar linhas e colunas baseados em um único eixo. Com isso podemos projetar e construir páginas na web responsivas sem o uso de propriedades estranhas como o float ou position em nosso código CSS.

Grid

Exemplo CSS Grid

Por outro lado, o Grid tem um sistema bidimensional que consegue criar tanto linhas horizontais como linhas verticais. Com a flexibilidade do Grid conseguimos obter layouts incríveis e não ficamos dependentes apenas do Flexbox.

Quais os principais elementos do CSS Flexbox?

Para entender as propriedades do Flexbox, devemos primeiro entender os seus 2 principais conceitos: Eixos Flex (Flex Axis) e Linhas Flex (Flex Lines). Toda essa ideia é baseada nos eixos que determinam as direções dos itens que estão dentro de um container flex.

A ilustração a seguir mostra quais os eixos definidos num container flex:

Eixos do conteiner

Eixo principal

É o eixo da linha do Flexbox onde os itens serão alocados. Por padrão, é definido sendo horizontal (row), mas pode ser mudado através da propriedade flex-direction.

Eixo Transversal

É o eixo perpendicular ao principal, ou seja, é um eixo que depende da direção do principal: se esse for horizontal a transversal vai ser vertical.

Início principal e Fim principal

São as bases de início e fim para os itens do container, também podem ser alterados por meio da propriedade flex-direction.

Início Transversal e Início Transversal

Nesse caso, são o início e fim das linhas transversais adicionadas ao container. São uma parte muito importante para o alinhamento vertical usando a propriedade align-items que veremos logo mais.

Tamanho principal e tamanho transversal: altura e largura de um flex item

O tamanho principal é a largura do container principal (também pode ser altura se a direção for trocada). No tamanho transversal é ao contrário, temos a altura do container transversal e se a direção for mudada, será a largura.

Flex container

É o principal elemento que envolve todos os itens de uma estrutura flex, nele é definido a propriedade display: flex.

Flex item

É o elemento-filho do Flex container, podemos ter quantos elementos forem necessários.

Propriedades pai do Flexbox

Para entender melhor os conceitos do Flexbox temos que entender todas as propriedades disponíveis para o Flex container. Separamos logo abaixo os principais atributos do elemento-pai: 

Display: definindo um flex container(inline ou block)

A primeira e mais importante propriedade serve para colocar todos os elementos-filhos dentro de um container Flex, nela podemos definir o valor flex ou inline-flex.

Definindo um flex container
 .flex-container {
     display: flex;
 } 

Flex-direction: definindo em qual direção o elemento flex será exibido

Aqui podemos escolher a direção na qual queremos apresentar os nossos itens. a partir do eixo principal conseguimos definir a direção que deve ser seguida. Imagine que o Flex container é um elemento que junta vários elementos-filhos em uma única direção e essa direção pode ser trocada com o flex-direction.

Definindo a direção e a ordem de exibição dos elementos
 .flex-container {
     flex-direction: row | row-reverse | column | column-reverse;
 } 

Flex-wrap: gerando quebras de linhas automática

Se você tentou utilizar o Flexbox mas se deparou com problemas na quebra de linha, saiba que esse comportamento é o padrão da ferramenta. Com a propriedade flex-wrap definimos se queremos ou não quebrar a linha ou até mesmo se queremos quebrar a linha “reversamente”.  

Quebras de linha CSS Flexbox
 .flex-container {
     flex-wrap: nowrap | wrap | wrap-reverse;
 } 

Flex-flow: definindo os eixos principal e transversal do container

Nessa propriedade, temos a junção do flex-direction com o flex-wrap, formando assim uma propriedade chamada shorthand, quando uma mesma declaração contém vários valores, como é o caso em algumas propriedades das cores. Consequentemente, temos a declaração dos eixos principais e transversais por meio desse campo. O valor padrão é row nowrap.

 .flex-container {
     flex-flow: row nowrap | row wrap | column nowrap | column wrap;
 } 

Flexbox justify-content/align-content: alinhando os elementos no eixo principal

justify-content

A propriedade justify-content auxilia no alinhamento dos itens no eixo principal do Flex container. Temos diversas opções de alinhamento e essa opção também funciona se a direção do eixo for mudada para vertical.

Alinhamento dos elementos no eixo principal
 .flex-container {
     justify-content:flex-start|flex-end|center|space-between|space-around|space-evenly;
 } 
  • flex-start (padrão): Os itens são postos no começo do eixo principal.
  • flex-end: Os itens são alocados no final do eixo principal.
  • center: Os itens são alinhados no meio do eixo.
  • space-between: O primeiro item fica no começo do eixo e o último no fim, os restantes ficam alinhados entre si no meio.
  • space-around: Os itens são distribuídos uniformemente dentro do eixo principal, sendo o espaçamento de cada par adjacente igual.O espaço vazio antes do primeiro e depois do último item é igual a metade do espaço entre cada par de itens adjacentes.
  • space-evenly: Parecido com os anteriores, os itens são colocados no eixo principal com espaçamentos equivalentes entre si.

Observação: Todos esses valores funcionam para o flex-direction: column.

align-content

Nessa propriedade, definimos a direção das linhas no eixo transversal do Flex container. Parecido com o justify-content, temos os mesmos valores para essa propriedade.

Alinhando a direção das linhas no eixo transversal
 .flex-container {
     align-content: stretch|flex-start|flex-end|center|
                    space-between|space-around|space-evenly;
 } 
  • stretch (padrão): As linhas são uniformemente distribuídas ao longo do eixo transversal, preenchendo todo o espaço disponível.
  • flex-start: As linhas são postas no começo do eixo transversal.
  • flex-end: As linhas são alocadas no final do eixo transversal.
  • center: As linhas são alinhadas no meio do eixo transversal.
  • space-between: A primeira linha fica no começo do eixo transversal e a última no fim, as restantes ficam alinhadas entre si no meio.
  • space-around: As linhas são distribuídas uniformemente dentro do eixo transversal, sendo o espaçamento de cada uma adjacente igual. O espaço vazio antes da primeira e depois da última linha é igual a metade do espaço entre cada par de linhas adjacentes.
  • space-evenly: Parecida com as anteriores, as linhas são colocadas no eixo transversal com espaçamentos equivalentes entre si.

Observação: Todos esses valores funcionam para o flex-direction: column.

Flexbox align-items: alinhando os elementos no eixo transversal

Aqui temos uma propriedade que altera a ocupação dos itens no eixo transversal dentro do Flex container. Temos os seguintes valores possíveis:

alinhando elementos no eixo transversal CSS Flexbox
 .flex-container {
     align-items: stretch | flex-start | flex-end | center | baseline;
 } 
  • stretch (padrão): Os itens são esticados para preencher todo o espaço vazio do eixo transversal.
  • flex-start: Os itens são alocados no começo do eixo transversal.
  • flex-end: Os itens são postos no fim do eixo transversal.
  • center: Os itens são distribuídos no meio do eixo transversal.
  • baseline: Por último, temos o alinhamento a partir da primeira letra do texto de cada item.

Propriedades filho do Flexbox

Igual ao pai, temos várias propriedades para os itens do Flexbox: podemos controlar o seu tamanho, ordenação de itens e até mesmo o alinhamento.

Flex-grow: distribuindo e aumentando o tamanho dos elementos do container 

Essa propriedade controla a proporção que um dos itens deve crescer caso seja preciso. Os valores aceitos são apenas números positivos e o valor padrão é 0.

Distribuindo valores dos elementos

Nesse caso, temos o primeiro e o último item com o valor de flex-grow: 2.

 .flex-item {
     flex-grow: número;
 } 

Flex-shrink: diminuindo o tamanho dos elementos do container

Nessa outra propriedade, definimos a proporção que queremos diminuir o item. Parecido com o flex-grow, temos o valor padrão de 0 e apenas números positivos são aceitos.

Diminuindo os elementos no container

Nesse caso, temos o primeiro e o último item com o valor de flex-shrink: 2.

 .flex-item {
     flex-shrink: número;
 } 

Flex-basis: definindo o tamanho inicial do elemento

Nessa propriedade, definimos a largura ou altura (dependendo da direção do eixo) inicial do item. Diferentemente das outras propriedades, esse campo aceita valores em percentual, em pixels e até mesmo a palavra auto, que é definida como padrão.

Definindo tamanho inicial dos elementos

Aqui temos em cada item o valor de flex-basis: 30%.

 .flex-item {
     flex-basis: número;
 } 

Flex

Essa propriedade define de forma abreviada as propriedades flex-grow, flex-shrink e flex-basis, com isso conseguimos de forma resumida declarar vários valores em uma propriedade só.

 .flex-item {
     flex: flex-grow flex-shrink flex-basis;
 } 

Flexbox order: determina a ordem que os elementos aparecem

Nessa propriedade, definimos a ordem dos itens individualmente. Por padrão a ordem vem da sintaxe do HTML, no entanto podemos trocar essa ordem a partir dessa propriedade. O valor pode ser apenas número e é aceito valores negativos.

Ordem de exibição dos elementos CSS Flexbox

Aqui definimos que o primeiro item tem a order: 3 e o segundo order: 2, mudando assim a ordem do terceiro item.

 .flex-item {
     order: número;
 } 

Flexbox align-self: alterando o alinhamento de um item separadamente

Essa propriedade permite sobrescrever o alinhamento do eixo transversal do item, definido pelo Flex container a partir da propriedade align-items. Temos os mesmos valores da outra propriedade só que definidos individualmente nesse caso.

Alinhando itens separadamente
 .flex-item {
     order: auto | stretch | flex-start | flex-end | center | baseline;
 } 
  • auto (padrão): Por padrão, o item segue o alinhamento do Flex container.
  • stretch: Estica o item em todo o espaço disponível no container pelo eixo transversal.
  • flex-start: Alinha o item para o começo do eixo transversal.
  • flex-end: Aloca o item para o fim do eixo transversal.
  • center: Centraliza o item no eixo transversal.
  • baseline: O item é alinhado a partir da primeira letra dos demais.

Quais as vantagens e desvantagens de usar o CSS Flexbox?

Meme CSS Flexbox

Diferentemente dessa imagem, não podemos utilizar o Flexbox em todas as nossas ocasiões, por isso iremos explicar para você em quais casos devemos realmente utilizar essa ferramenta.

Quando utilizar o Flexbox?

Sinceramente, utilize o CSS Flexbox sempre que puder. Para layouts unidimensionais, a utilização do Flex é muito poderosa, tanto para o controle dos itens, quanto para o controle do layout da tela, facilitando a vida de quem apenas utilizava o float e o position. Com o Flex container, vamos ter a possibilidade de controlar a altura e largura dos itens, se for necessário, também ocorrerá a quebra de linhas para que os itens não sejam sobrepostos. No fim podemos utilizar o Flexbox para criação de layouts de várias formas.

Exemplo de quando utilizar CSS Flexbox

Com o align-items e justify-content temos o controle do alinhamento dos eixos do nosso container, sendo assim temos uma diminuição do código CSS já que apenas precisamos escrever no parente. Como já vimos, o Flex container contém várias propriedades que ajudam na elaboração de layouts complexos, criando assim uma dependência maior para apenas um elemento.

Quando não utilizar o Flexbox?

Há casos onde precisamos adicionar um elemento, ou em um local fixo da tela, ou em um local onde o Flexbox não consegue alcançar. Da forma que foi construído o Flexbox, não conseguimos sair tão facilmente da sua estrutura-base de container e item.

Exemplo de imagem fora do container

Se você precisa criar diversas camadas para posicionar um único elemento na tela, provavelmente você está fazendo isso errado. Para esses casos, voltamos a utilizar as propriedades float e position para a alocação desses itens. Cria-se um objeto fixo no elemento ou então, um elemento que é posicionado relativamente a outro.

Exemplos de uso do CSS Flexbox para solucionar problemas na prática!

Rodapé fixo

Uma das tarefas mais árduas para a vida de um desenvolvedor front-end é criar uma página com o rodapé fixo, isso é, fazer um layout onde o footer fica sempre no fim da página. Existem algumas soluções na internet, como mostrado no CSS Sticky Footer, no entanto, é necessário ter uma estrutura de projeto relativamente complexa e não seria muito simples de implementar em um site já construído.

A ideia aqui é utilizar as propriedades que vimos do Flexbox para deixar o rodapé sempre no final da página. Para o começo, transformaremos o nosso elemento body em um Flex container, e em seguida trocaremos a direção horizontal para vertical. Por fim, definiremos a altura mínima de 100vh (equivale a 100% do viewport). Para os itens utilizaremos as tags header, main e footer. No elemento main, colocaremos a propriedade flex-grow com o valor de 1 e pronto, terminamos o nosso rodapé fixo:

Rodapé fixo

HTML:

 <body>
     <header>
         Header
     </header>
     <main>
         Main
     </main>
     <footer>
         Footer
     </footer>
 </body> 

CSS:

 body {
     /* Código principal */
     display: flex;
     flex-direction: column;
     min-height: 100vh;
     /* Código extra */
     margin: 0;
     text-align: center;
     font-family: system-ui;
     font-size: 1.5rem;
     color: honeydew;
 }
 header {
     /* Código extra */
     padding: 16px 8px;
     background-color: deepskyblue;
 }
 main {
     /* Código principal */
     flex-grow: 1;
     /* Código extra */
     padding: 16px 8px;
     margin: 16px;
     border-radius: 8px;
     color: lemonchiffon;
     background-color: royalblue;
 }
 footer {
     /* Código extra */
     padding: 16px 8px;
     background-color: deepskyblue;
 } 

Centralização vertical

Não ter por um bom tempo uma maneira simples de centralizar verticalmente um elemento no CSS deixou uma mancha sombria na sua reputação.

O pior é que as técnicas utilizadas para o funcionamento da centralização vertical acabavam sendo desconhecidas e não muito intuitivas, enquanto que as escolhas óbvias (como o vertical-align: middle) não funcionavam da maneira que você esperava.

Algumas dessas opções para o centralização vertical variam de margens negativas e alguns hacks com as células de tabela a altura dos pseudo-elementos. Contudo, mesmo que algumas das técnicas cheguem a funcionar, elas não funcionam em todas as situações. 

Utilizando o Flexbox, você vai ver que essa árdua tarefa não é nada! Você consegue alinhar tanto todos os elementos do container como também algum item individual.

Centralização Vertical exemplo

Aqui, além de alinhar a caixa com o conteúdo, alinhamos o também o conteúdo, tudo com apenas algumas linhas de código.

HTML:

 <body>
     <div class="caixa">
         <div class="conteudo">
             <h1>
                 Título
             </h1>
             <p>
                lorem...
             </p>
         </div>
     </div>
 </body> 

CSS:

 * {
     /* Código principal */
     margin: 0px;
     box-sizing: border-box;
 }
 body {
     /* Código principal */
     min-height: 100vh;
     display: flex;
     align-items: center;
 }
 .caixa {
     /* Código principal */
     display: flex;
     flex-wrap: wrap;
     align-content: center;
     height: 300px;
     /* Código extra */
     margin: 0 16px;
     background-color: hsla(31,15%,50%,.1);
     padding: 16px;
     border-radius: 8px;
     width: 100%;
 } 

Sistemas de Grid

A vasta maioria dos sistemas de grid utilizavam float ou inline-block, no entanto, nenhuma dessas alternativas eram realmente úteis, isso porque essas propriedades não foram criadas para esse propósito e com isso acabavam tendo sérios problemas e limitações.

A utilização do float necessita que você utilize uma técnica chamada clear, que é uma série de hacks para o layout ficar correto. Contudo, isso pode acabar apenas deixando o seu código maior e mais sujo posteriormente. 

Além disso, é preciso utilizar os pseudo-elementos before e after para fazer essa limpeza de layout, prevenindo assim a utilização para outros casos.

Layouts que utilizam o inline-block contêm uma série de problemas de espaços em branco entre os itens. algumas das soluções para esses problemas são realmente estranhas e chatas.

O Flexbox elimina todos esses problemas e abre um novo leque de possibilidades.

Vantagens do sistema de grid do Flexbox

Os sistemas de grid usualmente vem com uma infinidade de opções de dimensionamento, mas, na grande maioria dos casos, você quer apenas 2 ou 3 elementos lado a lado. Dado essa situação, por que devemos colocar classes de dimensionamento em cada célula?

Na lista abaixo, deixamos alguns critérios de um sistema de grid ideal. Graças ao Flexbox, a maioria dos recursos já é obtido.

  • Por padrão, cada célula do grid tem que ter o mesmo tamanho das outras células de outras linhas. Basicamente, todas se juntam por padrão.
  • Para um controle melhor, você pode criar classes auxiliares para redimensionar os itens. Sem essas classes, temos os itens se adequando automaticamente.
  • Para grids responsivos, você pode adicionar classes com media query específicos.
  • Os itens individuais podem ser alinhados verticalmente para cima, baixo e meio.
  • Já que queremos que as células tenham classes específicas para cada caso, podemos criar uma única classe no container para evitar repetições desnecessárias.
  • Grids podem ser aninhados em quantos níveis de profundidade forem necessários.

Grid básico

O grid abaixo não tem nenhuma largura especificada. Eles uniformemente se dividem entre si e se expandem para preencher toda a coluna. Eles são iguais de altura e largura.

Grid Básico

Tamanho individual

Quando a largura automática não é o que você quer, você pode adicionar classes para aumentar o tamanho das células individuais. Os itens que não tiverem a classe, vão ocupar apenas o restante do espaço.

Tamanho individual dos elementos na Grid

Código

O código do HTML em si vai se adequar para as suas necessidades, por isso deixamos aqui um exemplo simples:

        <div class="Grid Grid--gutters u-textCenter">
             <div class="Grid-cell">
                 <div class="Demo">1/2</div>
             </div>
             <div class="Grid-cell">
                 <div class="Demo">1/2</div>
             </div>
         </div>
         <div class="Grid Grid--gutters u-textCenter">
             <div class="Grid-cell">
                 <div class="Demo">1/3</div>
             </div>
             <div class="Grid-cell">
                 <div class="Demo">1/3</div>
             </div>
             <div class="Grid-cell">
                 <div class="Demo">1/3</div>
             </div>
         </div>
         <div class="Grid Grid--gutters u-textCenter">
             <div class="Grid-cell">
                 <div class="Demo">1/4</div>
             </div>
             <div class="Grid-cell">
                 <div class="Demo">1/4</div>
             </div>
             <div class="Grid-cell">
                 <div class="Demo">1/4</div>
             </div>
             <div class="Grid-cell">
                 <div class="Demo">1/4</div>
             </div>
         </div> 

Para o código de estilo, temos:

 .Grid {
     display: flex;
 }
 .Grid-cell {
     flex: 1;
 }
 /* Com espaçamento */
 .Grid--gutters {
     margin: -1em 0 0 -1em;
 }
 .Grid--gutters > .Grid-cell {
     padding: 1em 0 0 1em;
 }
 /* Alinhamento por linha */
 .Grid--top {
     align-items: flex-start;
 }
 .Grid--bottom {
     align-items: flex-end;
 }
 .Grid--center {
     align-items: center;
 }
 /* Alinhamento por célula */
 .Grid-cell--top {
     align-self: flex-start;
 }
 .Grid-cell--bottom {
     align-self: flex-end;
 }
 .Grid-cell--center {
     align-self: center;
 }
 /* Classes base */
 .Grid--fit > .Grid-cell {
     flex: 1;
 }
 .Grid--full > .Grid-cell {
     flex: 0 0 100%;
 }
 .Grid--1of2 > .Grid-cell {
     flex: 0 0 50% 
 }
 .Grid--1of3 > .Grid-cell {
     flex: 0 0 33.3333% 
 }
 .Grid--1of4 > .Grid-cell {
     flex: 0 0 25% 
 }
 /* Telas pequenas para médias */
 @media (min-width: 24em) {
     .small-Grid--fit > .Grid-cell {
         flex: 1;
    }
     .small-Grid--full > .Grid-cell {
         flex: 0 0 100%;
    }
     .small-Grid--1of2 > .Grid-cell {
         flex: 0 0 50% 
    }
     .small-Grid--1of3 > .Grid-cell {
         flex: 0 0 33.3333% 
    }
     .small-Grid--1of4 > .Grid-cell {
         flex: 0 0 25% 
    }
 }
 /* Telas grandes */
 @media (min-width: 48em) {
     .large-Grid--fit > .Grid-cell {
         flex: 1;
    }
     .large-Grid--full > .Grid-cell {
         flex: 0 0 100%;
    }
     .large-Grid--1of2 > .Grid-cell {
         flex: 0 0 50% 
    }
     .large-Grid--1of3 > .Grid-cell {
         flex: 0 0 33.3333% 
    }
     .large-Grid--1of4 > .Grid-cell {
         flex: 0 0 25% 
    }
 } 

Compatibilidade com navegadores

Compatibilidade CSS Flexbox com navegadores

Como vemos na imagem, a compatibilidade do Flexbox no ano de 2021 é de mais de 99%! Isso indica que não devemos nos preocupar tanto em dar suporte para navegadores mais antigos.

Também há uma lista de bugs do Flexbox no Github que pode auxiliar você na hora do desenvolvimento.

O Flexbox foi criado para ser flexível e robusto. Com ele, conseguimos criar diversos layouts para desktop, tablet e mobile. A partir do Flex container, temos toda a lógica dos eixos principal e transversal, contamos também com propriedades para alinhar os seus itens, aumentar ou diminuir e até mesmo reorganizar a ordenação.

Contamos também com a possibilidade de mudar a direção do nosso container para realocar os itens horizontais e transformá-los em itens verticais. Com poucas linhas, podemos criar uma sequência de cartões que vão conter o mesmo tamanho ou também alinhar o cabeçalho de página com a logo no começo do eixo principal e alguns textos no fim desse container.

Quer entender mais sobre o CSS? Então, confira 5 dicas essenciais para entendê-lo com mais facilidade.