CSS - FlexBox

Problemas de alinhamento e espaçamento no HTML

Se você já desenvolveu páginas html já deve ter se deparado com problemas de alinhamento dos itens na página.
Quando falamos de alinhar um item a esquerda ou a direita da linha isso não é um problema, só tem ele mesmo.
Contudo o problema aparece quando temos mais de um elemento a ser alinhado, por exemplo, um a direita e outro a esquerda da tela.

Se você conhece html sabe que isso é impossível pelas tags inline ( em linha ). As tags inline ocupam só o espaço que precisam e o browser alinha elas da direita para a esquerda automaticamente sem chance de nenhum recurso html alterar essa formatação.

Novamente, se você conhece html sabe que isso é impossível pelas tags block (bloco). As tags inblock ocupam totalmente uma linha de maneira exclusiva e com isto o primeiro elemento seria exibido numa linha e o próximo na linha logo abaixo.

Como no DOM só temos esses 2 tipos de elemento (inline e bloco) como faríamos para pegar 2 elementos, um alinhado à direita e outro à esquerda ou mesmo um terceiro no centro ou, pior ainda, dar entre os elementos um espaçamento igualitário e responsivo de maneira que ele se ajuste automaticamente esses itens a largura da tela de exibição.

Como diriam o pessoal do Casseta e Planeta, não tema, não há problema...o flexbox Tabajara vai resolver seu problema. E resolve mesmo, sem brincadeira.

Para que Serve o FlexBox ?

Costumo dizer que a formatação de texto é para o html o que o FlexBox é para a CSS em termos de recursos. O casal perfeito.

Posicionar os elementos corretamente numa página HTML algumas vezes parece impossível e, às vezes, perdemos um tempo precioso nisso.
Contudo quanto melhor conhecermos os recursos de posicionamento menos tempo perdemos com esses 'acertos'.
E o flexbox é um recurso único que todos desenvolvedores devem conhecer.

FlexBox permite você alinhar elementos à direita, à esquerda e principalmente ao centro de maneira que nenhum outro recurso css ou html consegue fazer e tem tantos recursos que o FlexBox acaba ficando complexo por causa desse leque de recursos que propicia ganhos significativos no laioute de uma página.

Dicas de Ouro - Pode guardar no seu cinto de utilidade

Dica 1 : O alinhamento do item sempre se refere ao elemento container dele.
O elemento container mestre é a tag body e a partir dele temos todas as tags filhas sejam quantas forem.

Dica 2 : o estilo align-items atua no alinhamento vertical do item, alinha ao topo (start ou baseline), meio (center), rodapé (end).

Dica 3 : o estilo justify-content atua no alinhamento horizontal, alinha à esquerda (left), à direita (right) e ao centro / meio (center).

style="height:auto" ajusta a altura do flexbox para que não ocupe mais espaço que o necessário;

Dica 5 : Um recurso que só o flexbox oferece é espaçar igualitariamente os itens igualitáriamente na linha e, melhor ainda, responsivo. Show de bola.

Exemplo 1 - Sem Flexbox

Neste primeiro exemplo mostro algumas divs sem muito floreado. Apliquei alguns estilos para formatar a div e a área ocupada por elas ( container ) para melhor visualizar os efeitos e áreas atingidas por eles.

Código:

<style>
        .container {
            background-color: #fff;
            border: 2px solid #333;
            margin-bottom: 20px;
            padding: 10px;
        }

        .circle {
            width: 50px;
            height: 50px;
            border-radius: 50%;
            display: flex;
            justify-content: center;
            align-items: center;
            font-weight: bold;
            margin: 5px;
        }

        .backColor1 {background-color: #ffb3ba;}
        .backColor2 {background-color: #baffc9;}
        .backColor3 {background-color: #bae1ff;}
        .backColor4 {background-color: #ffffba;}
        .backColor5 {background-color: #ffdfba;}
    </style>


<div class="container">
<div class="circle backColor1">Item 0</div>
<div class="circle backColor2">Item 1</div>
<div class="circle backColor3">Item 2</div>
<div class="circle backColor4">Item 3</div>
<div class="circle backColor5">Item 4</div>
<div class="circle backColor1">Item 5</div>
<div class="circle backColor2">Item 6</div>
<div class="circle backColor3">Item 7</div>
<div class="circle backColor4">Item 8</div>
<div class="circle backColor5">Item 9</div>
</div>

Como é exibido:

Item 0
Item 1
Item 2
Item 3
Item 4
Item 5
Item 6
Item 7
Item 8
Item 9

A classe container delimita a região do documento que estamos trabalhando e, para facilitar, coloquei o fundo em branco.

A classe circle faz a div ficar circular o que destaca bem um elemento de outro.

As classes backColor1 a 5 dão uma cor diferenciada para cada elemento, novamente para deixar claro e destacar cada elemento.

Até aqui tudo tem aparência de uma grande porcaria, mas a intenção é demonstrar cada recurso separadamente demonstrando como ele influencia a apresentação visual do elemento.

Aplicando o estilo Default do Flex - Row (linha)

A aplicação do estilo flex-container com o style flex faz o controle div que é em bloco virar inline, como se aplicássemos o estilo display:inline. Todos os itens do flexbox serão exibidos na mesma linha que é o default do FlexBox, ROW. É o mesmo que no style selecionarmos style="flex-direction:row".

Código:

.flex-container {
   display: flex;
   height: 200px;
   margin-bottom: 10px;
}

<div class="container">
   <div class="flex-container">
   <div class="circle backColor1">Item 0</div>
   <div class="circle backColor2">Item 1</div>
   <div class="circle backColor3">Item 2</div>
   <div class="circle backColor4">Item 3</div>
   <div class="circle backColor5">Item 4</div>
   <div class="circle backColor1">Item 5</div>
   <div class="circle backColor2">Item 6</div>
   <div class="circle backColor3">Item 7</div>
   <div class="circle backColor4">Item 8</div>
   <div class="circle backColor5">Item 9</div>

Como é exibido:

Item 0
Item 1
Item 2
Item 3
Item 4
Item 5
Item 6
Item 7
Item 8
Item 9

Importante : Note que o estilo alterou a div interna (class="flex-container"), mas não a externa (class="container") e é por esse motivo que a classe container ficou tão alta. Quando a tag container foi definida não havia a tag flex e por esse motivo ao 'renderizar' a tag container ele usou o mesmo espaço como se os elementos a seguir não fossem flex, que é o default do browser.

Para efeitos didáticos, Não gostou, quer que os elementos sejam separados em linhas diferentes, mude o estilo para style="flex-direction:column" e ficará assim:

Item 0
Item 1
Item 2
Item 3
Item 4
Item 5
Item 6
Item 7
Item 8
Item 9





Você deve ter notado que o container não acompanhou a altura dos elementos dentro do flex. É verdade, quando você usa o flex precisa definir a altura do container já que ao usar flex o posicionamento deles muda.

Definindo um espaçamento padrão para o estilo Flex - Row (linha)

Neste caso queremos dar um espaçamento homogêneo entre os elementos do flex, como no grid do BootStrap.
Note que você não define o espaçamento mas sim o browser que dará o mesmo espaçamento para todos os elementos ( se possível) automaticamente dependendo da lagura da tela de exibição do browser.
Basta mudar o estilo para style="justify-content: space-between" e veja como fica:

Código:

<div class="container">
   <div class="flex-container" style="justify-content: space-between">
      <div class="circle backColor1">Item 0</div>
      <div class="circle backColor2">Item 1</div>
      <div class="circle backColor3">Item 2</div>
      <div class="circle backColor4">Item 3</div>
      <div class="circle backColor5">Item 4</div>
      <div class="circle backColor1">Item 5</div>
      <div class="circle backColor2">Item 6</div>
      <div class="circle backColor3">Item 7</div>
      <div class="circle backColor4">Item 8</div>
      <div class="circle backColor5">Item 9</div>
      </div> </div>

Como é exibido:

Item 0
Item 1
Item 2
Item 3
Item 4
Item 5
Item 6
Item 7
Item 8
Item 9

Importante : Não foi definido o atributo wrap no flex o que faz com os elementos sejam 'sempre' na mesma linha.
Se você reduzir a largura da tela verá que o espaçamento entre os elementos será reduzido e todos os elementos são exibidos na mesma linha. Com o parâmetro wrap o espaçamento seria mantido e quando o elemento não 'coubesse' na largura da tela ele seria simplesmente jogado para a linha de baixo.

Dando um espaçamento entre cada item do Flex - Row (linha) com wrap

Num exemplo acima não usamos o parâmetro wrap então todos os elementos do flex serão mantidos na linha.
Para isto o browser irá alterar o espaçamento entre os elementos tentando manter eles na mesma linha.
Neste exemplo abaixo setamos o parâmetro wrap o que fará com que o espaçamento entre os elementos seja mantido e se o elemento não 'couber' na largura da tela ele será colocado na linha logo abaixo.

Código:

<div class="container">
   <div class="flex-container" style="justify-content: space-between; flex-wrap: wrap;">
      <div class="circle backColor1">Item 0</div>
      <div class="circle backColor2">Item 1</div>
      <div class="circle backColor3">Item 2</div>
      <div class="circle backColor4">Item 3</div>
      <div class="circle backColor5">Item 4</div>
      <div class="circle backColor1">Item 5</div>
      <div class="circle backColor2">Item 6</div>
      <div class="circle backColor3">Item 7</div>
      <div class="circle backColor4">Item 8</div>
      <div class="circle backColor5">Item 9</div>
   </div>
</div>

Como é exibido:

Item 0
Item 1
Item 2
Item 3
Item 4
Item 5
Item 6
Item 7
Item 8
Item 9

Para testar redimensione horizontalmente a tela...vai ver que no exemplo anterior os itens ficam sempre numa única linha e neste exemplo quando não cabe ele joga o elemento para a linha de baixo;

Corrigindo a altura do Flex do exemplo acima (Flex-Row-com wrap)

Basta colocar no estilo height: auto. Veja como fica:

Item 0
Item 1
Item 2
Item 3
Item 4
Item 5
Item 6
Item 7
Item 8
Item 9

Alinhando os itens do Flex - Row (linha) no centro da linha

No exemplo mencionado anteriormente nossa classe .flex-container tem uma propriedade que barra a centralizaçã, mais precisamente o estilo height: 200px;.
Isto faria com que nossos elementos seriam alinhados ao centro nesses 200 pixels. Prefiro mudar a classe e centrar na linha os elemento. Para isso criei uma nova classe chamada flex-center:

Código:

.flex-center {
            display: flex;
            align-items: center;
            justify-content: center;
}

Como é exibido:

Item 0
Item 1
Item 2
Item 3
Item 4
Item 5
Item 6
Item 7
Item 8
Item 9

Pode guardar o exemplo acima no seu cinto de utilidades...a gente usa isso muito para centralizar divs.

Alinhando os itens do Flex - Row (linha) no final da linha

E se quisessemos que os elementos fossem alinhados com a margem a direita da página ?
Neste caso se houver apenas um elemento ele será alinhado à direita da página.
Se houverem 2 elementos o primeiro será exibido à esquerda do segundo e assim por diante. Para usar este efeito criei a classe flex-end ( end = direita da página ).

Código:

.flex-end {
            display: flex;
            align-items:end;
            justify-content: flex-end;
}

Como é exibido:

Item 0
Item 1
Item 2
Item 3
Item 4
Item 5
Item 6
Item 7
Item 8
Item 9

Este recurso é muito usado quando queremos exibir datas e assinaturas numa página web.

Bagunçando o coreto...ou melhor a ordem dos elementos do Flex

O Flex possui tantos recursos que por mais que a gente use está sempre aprendendo.

Como vimos nos exemplos acima o flex posicina um elemento após o outro conforme vão sendo declarados.

Mas e se precisássemos mudar a ordem de exibição ? Sem problemas..use a propriedade order: x onde x é um número de 0 a n indicando a ordem do elemento sendo que 0 vem antes de n contando da esquerda para a direita. Peguei os itens de 0 a 4 coloquei na ordem inversa, 5 a 1.Veja como fica

Como é exibido:

Item 0
Item 1
Item 2
Item 3
Item 4

No exemplo assim declarei os elementos na ordem 0 a 4 e os exibi na ordem inversa pelo parâmetro order.

E se quiséssemos a largura dos elementos variável ?

Se lembra do grid do BootStrap ? O grid divide a linha em 12 partes iguais e se a gente colocar o parâmetro col-5 significa que a coluna iria agrupar 5 espaços numa única coluna

No exemplo abaixo farei a primeira coluna ter a largura 1, a segunda largura 5, a terceira 1, a quarta 5 e a última 1. Veja o código:

Código:

<div class="container">
      <div class="flex-container">
      <div class="circle backColor1" style="flex-grow: 1">Item 0</div>
      <div class="circle backColor2" style="flex-grow: 5">Item 1</div>
      <div class="circle backColor3" style="flex-grow: 2">Item 2</div>
      <div class="circle backColor4" style="flex-grow: 4">Item 3</div>
      <div class="circle backColor5" style="flex-grow: 3">Item 4</div>
   </div>
</div>

Como é exibido:

Item 0
Item 1
Item 2
Item 3
Item 4

O recurso acima é muito bom para criar barra de links personalidados.

E o alinhamento vertical dos elementos ?

Para fechar com chave de ouro uma outra formatação possível é fazer um elemento ser posicionado verticalmente dentro do seu container. Veja o exemplo:

Código:

<div class="container">
   <div class="flex-container">
   <div class="circle backColor1" style="align-self: flex-start">Item 0</div>
      <div class="circle backColor2" style="align-self: center">Item 1</div>
      <div class="circle backColor3" style="align-self: flex-end">Item 2</div>
      <div class="circle backColor4" style="align-self: stretch; height: auto"> Item 3 </div>
      <div class="circle backColor5">Item 4</div>
   </div>
</div>

Como é exibido:

Item 0
Item 1
Item 2
Item 3
Item 4

O parâmetro style="align-self: flex-start" faz com que o elemento seja posicionado vertialmente no topo do container, ou seja, na parte de cima do container.

O parâmetro style="align-self: center" alinha o elemento verticalmente no centro do container.

O parâmetro style="align-self: flex-end alinha o elemento verticalmente no rodapé do container.

O parâmetro style="align-self: stretch; height: auto" parece bruxaria, estica verticalmente o elemento para que ele comece no topo do container e termine no rodaé do Container.

O último item 4 é o default do alinhamento vertical do FlexBox, no topo.

Finalizando

Faça alguns testes com o FlexBox. O tempo que você vai gastar aprendendo ele vai ser 1 milionésimo do tempo que você irá demorar se não aprender.
Como disse, o FlexBox é complexo mas os recursos de posicionamento que ele dá ao html nenhum outro recurso do html / css irá proporcionar.