Conceitos básicos do flexbox

Flexible Box Module, geralmente chamado de flexbox, foi projetado como um modelo de layout unidimensional, e como um método que poderia oferecer distribuição de espaço entre itens numa interface e capacidades poderosas de alinhamento. Este artigo fornece um resumo das principais funcionalidades do flexbox, que exploraremos com mais detalhes no restante destes guias.

Quando nós descrevemos o flexbox como sendo de uma dimensão, nós estamos descrevendo o fato de que o flexbox lida com o layout numa dimensão de cada vez - quer seja como uma linha ou como uma coluna. Isto pode ser contrastado com o modelo bidimensional de CSS - Grid Layout, que controla ao mesmo tempo as colunas e linhas.

Os dois eixos do flexbox

Ao trabalhar com o flexbox, você precisa pensar em termos de dois eixos — o eixo principal e o eixo transversal. O eixo principal é definido pela propriedade flex-direction e o eixo transversal corre perpendicular a ele. Tudo o que nós fazemos com o flexbox remete a esses eixos, por isso vale a pena entender como eles funcionam desde o início.

O eixo principal

O eixo principal é definido por flex-direction, que tem quatro valores possíveis:

  • row
  • row-reverse
  • column
  • column-reverse

Se você escolher row ou row-reverse, seu eixo se moverá junto com a linha na direção inline.

If flex-direction is set to row the main axis runs along the row in the inline direction.

Escolha column ou column-reverse e seu eixo principal se moverá do topo da página para baixo — na direção block.

If flex-direction is set to column the main axis runs in the block direction.

O eixo transversal

O eixo transversal se move perpendicularmente ao eixo principal, logo se o seu flex-direction (eixo principal) está definido como row ou row-reverse, o eixo transversal estará na direção das colunas.

If flex-direction is set to row then the cross axis runs in the block direction.

Se o seu eixo principal for column ou column-reverse, então o eixo transversal se moverá na direção das linhas.

If flex-direction is set to column then the cross axis runs in the inline direction.

Entender qual eixo é o que é importante quando começamos a ler sobre alinhar ou justificar itens flexíveis (flex items); O Flexbox possui propriedades que alinham e justificam o conteúdo ao longo de um eixo ou outro.

Linhas de Início e Fim

Outra área vital de entendimento é como o Flexbox não faz nenhuma premissa sobre o modo de escrita do documento. No passado, o CSS utilizava mais o modo de escrita horizontal e da esquerda para a direita. Métodos modernos de layout abrangem uma variedade de modos de escrita e, portanto, não assumimos mais, que uma linha de texto comece no canto superior esquerdo do documento e corra para o lado direito, com novas linhas aparecendo umas sobre as outras.

Você pode ler mais sobre o relacionamento entre Flexbox e a especificação do modo de escrita em um artigo posterior, no entanto, a descrição a seguir deverá ajudar a explicar porque não falamos sobre esquerda e direita e em cima e em baixo quando descrevemos a direção em que nossos itens flexíveis fluem.

Se o flex-direction é row (linha) e eu estou trabalhando em Inglês, então a borda inicial do eixo principal estará a esquerda e a borda final a direita.

Working in English the start edge is on the left.

Se eu trabalhar em Árabe, a borda inicia do meu eixo principal estará à direita e a borda final à esquerda.

The start edge in a RTL language is on the right.

Nos dois casos, a borda inicial do eixo transversal está na parte superior do contêiner flexível e a borda final na parte inferior, pois os dois idiomas têm um modo de escrita horizontal.

Depois de um tempo, pensar no início e no final, e não na esquerda e na direita, se torna natural e será útil para você quando estiver lidando com outros métodos de layout, como CSS Grid Layout, que seguem os mesmos padrões.

O contêiner flexível

Uma área de um documento criada usando o flexbox  é chamada de contêiner flex. Para criar um Contêiner Flex, definimos o valor da propriedade display do contêiner da área como flex ou inline-flex. Assim que fizermos isso, os filhos diretos desse contêiner tornam-se itens flexíveis. Como em todas as propriedades do CSS, alguns valores iniciais são definidos; portanto, ao criar um Contêiner Flex, todos os itens flexíveis contidos nele se comportarão da seguinte maneira.

Os itens são exibidos em uma linha (a propriedade flex-direction  padrão é row).

  • Os itens começam na borda inicial do eixo principal.
  • Os itens não se esticam na dimensão principal, mas podem encolher.
  • Os itens serão esticados para preencher o tamanho do eixo transversal.
  • A propriedade flex-basis estará configurada para auto.
  • A propriedade flex-wrap estará configurada como nowrap.

O resultado é que todos os itens serão alinhados em uma linha, usando o tamanho do conteúdo como o tamanho no eixo principal. Se houver mais itens do que pode caber no container, eles não vão quebrar, mas, ao contrário, irão vazar. Se alguns itens forem mais altos que outros, todos os itens se estenderão ao longo do eixo transversal para preencher seu tamanho total.

Você pode ver no exemplo prático abaixo como isso ficará. Tente editar os itens ou adicionar itens adicionais para testar o comportamento inicial do Flexbox.

 

Alterando a "flex-direction"

Adicionando a propriedade flex-direction ao contêiner flex permite alterar a direção na qual nossos itens flex são exibidos. Configurando flex-direction: row-reverse a inversão de linha manterá os itens exibidos ao longo da linha, no entanto, as linhas inicial e final são alteradas.

Se mudarmos a flex-direction para a coluna, o eixo principal muda e nossos itens agora são exibidos em uma coluna. Defina a column-reverse e as linhas inicial e final serão novamente trocadas.

O exemplo dinâmico abaixo tem a flex-direction definida como row-reverse. Experimente os outros valores - row, column e column-reverse - para ver o que acontece com o conteúdo.

Container flexível de varias linhas com 'flex-wrap'

Embora o flexbox seja um modelo unidimensional, é possível fazer com que nossos itens flexíveis sejam agrupados em várias linhas. Ao fazer isso, 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 de ambos os lados.

Para causar o comportamento de quebra adicione a propriedade flex-wrap com o valor wrap. Agora, se os itens forem muito grandes para serem exibidos em uma linha, eles serão agrupados em outra linha. O exemplo dinamico abaixo cotém itens aos quais foi dadda uma largura, sendo a largura total dos itens muito grande para o container flexível. Como o flex-wrap está definido como wrap, os itens serão dividos. Defina para nowrap, que também é o valor inicial, e eles encolherão para caber no contêiner porque estão usando valores iniciais de flexbox que permitem que os itens encolham. O uso do nowrap causaria um vazamento se os itens não encolhessem ou não diminuíssem o suficiente para caber.

Find out more about wrapping flex items in the guide Mastering Wrapping of Flex Items.

The flex-flow shorthand

You can combine the two properties flex-direction and flex-wrap into the flex-flow shorthand. The first value specified is flex-direction and the second value is flex-wrap.

In the live example below try changing the first value to one of the allowable values for flex-direction - row, row-reverse, column or column-reverse, and also change the second to wrap and nowrap.

Properties applied to flex items

To have more control over flex items we can target them directly. We do this by way of three properties:

We will take a brief look at these properties in this overview, and you can gain a fuller understanding in the guide Controlling Ratios of Flex Items on the Main Axis.

Before we can make sense of these properties we need to consider the concept of available space. What we are doing when we change the value of these flex properties is to change the way that available space is distributed amongst our items. This concept of available space is also important when we come to look at aligning items.

If we have three 100 pixel-wide items in a container which is 500 pixels wide, then the space we need to lay out our items is 300 pixels. This leaves 200 pixels of available space. If we don’t change the initial values then flexbox will put that space after the last item.

This flex container has available space after laying out the items.

If we instead would like the items to grow and fill the space, then we need to have a method of distributing the leftover space between the items. This is what the flex properties that we apply to the items themselves, will do.

The flex-basis property

The flex-basis is what defines the size of that item in terms of the space it leaves as available space. The initial value of this property is auto — in this case the browser looks to see if the items have a size. In the example above, all of the items have a width of 100 pixels and so this is used as the flex-basis.

If the items don’t have a size then the content's size is used as the flex-basis. This is why when we just declare display: flex on the parent to create flex items, the items all move into a row and take only as much space as they need to display their contents.

The flex-grow property

With the flex-grow property set to a positive integer, flex items can grow along the main axis from their flex-basis. This will cause the item to stretch and take up any available space on that axis, or a proportion of the available space if other items are allowed to grow too.

If we gave all of our items in the example above a flex-grow value of 1 then the available space in the flex container would be equally shared between our items and they would stretch to fill the container on the main axis.

The flex-grow property can be used to distribute space in proportion. If we give our first item a flex-grow value of 2 and the other items a value of 1, 2 parts will be given to the first item (100px out of 200px in the case of the example above), 1 part each the other two (50px each out of the 200px total).

The flex-shrink property

Where the flex-grow property deals with adding space in the main axis, the flex-shrink property controls how it is taken away. If we do not have enough space in the container to lay out our items and flex-shrink is set to a positive integer the item can become smaller than the flex-basis. As with flex-grow different values can be assigned in order to cause one item to shrink faster than others — an item with a higher value set for flex-shrink will shrink faster than its siblings that have lower values.

The minimum size of the item will be taken into account while working out the actual amount of shrinkage that will happen, which means that flex-shrink has the potential to appear less consistent than flex-grow in behavior. We’ll therefore take a more detailed look at how this algorithm works in the article Controlling Ratios of items along the main axis.

Note that these values for flex-grow and flex-shrink are proportions. Typically if we had all of our items set to flex: 1 1 200px and then wanted one item to grow at twice the rate, we would set that item to flex: 2 1 200px. However you could use flex: 10 1 200px and flex: 20 1 200px if you wanted.

Shorthand values for the flex properties

You will very rarely see the flex-grow, flex-shrink, and flex-basis properties used individually; instead they are combined into the flex shorthand. The flex shorthand allows you to set the three values in this order — flex-grow, flex-shrink, flex-basis.

The live example below allows you to test out the different values of the flex shorthand; remember that the first value is flex-grow. Giving this a positive value means the item can grow. The second is flex-shrink — with a positive value the items can shrink, but only if their total values overflow the main axis. The final value is flex-basis; this is the value the items are using as their base value to grow and shrink from.

There are also some predefined shorthand values which cover most of the use cases. You will often see these used in tutorials, and in many cases these are all you will need to use. The predefined values are as follows:

  • flex: initial
  • flex: auto
  • flex: none
  • flex: <positive-number>

Setting flex: initial resets the item to the initial values of Flexbox. This is the same as flex: 0 1 auto. In this case the value of flex-grow is 0, so items will not grow larger than their flex-basis size. The value of flex-shrink is 1, so items can shrink if they need to rather than overflowing. The value of flex-basis is auto. Items will either use any size set on the item in the main dimension, or they will get their size from the content size.

Using flex: auto is the same as using flex: 1 1 auto; everything is as with flex:initial but in this case the items can grow and fill the container as well as shrink if required.

Using flex: none will create fully inflexible flex items. It is as if you wrote flex: 0 0 auto. The items cannot grow or shrink but will be laid out using flexbox with a flex-basis of auto.

The shorthand you often see in tutorials is flex: 1 or flex: 2 and so on. This is as if you used flex: 1 1 0. The items can grow and shrink from a flex-basis of 0.

Try these shorthand values in the live example below.

Alignment, justification and distribution of free space between items

A key feature of flexbox is the ability to align and justify items on the main- and cross-axes, and to distribute space between flex items.

align-items

The align-items property will align the items on the cross axis.

The initial value for this property is stretch and this is why flex items stretch to the height of the tallest one by default. They are in fact stretching to fill the flex container — the tallest item is defining the height of that.

You could instead set align-items to flex-start in order to make the items line up at the start of the flex container, flex-end to align them to the end, or center to align them in the centre. Try this in the live example — I have given the flex container a height in order that you can see how the items can be moved around inside the container. See what happens if you set the value of align-items to:

  • stretch
  • flex-start
  • flex-end
  • center

justify-content

The justify-content property is used to align the items on the main axis, the direction in which flex-direction has set the flow. The initial value is flex-start which will line the items up at the start edge of the container, but you could also set the value to flex-end to line them up at the end, or center to line them up in the centre.

You can also use the value space-between to take all the spare space after the items have been laid out, and share it out evenly between the items so there will be an equal amount of space between each item. Or, to cause an equal amount of space on the right and left of each item use the value space-around.

Try the following values of justify-content in the live example:

  • stretch
  • flex-start
  • flex-end
  • center
  • space-around
  • space-between

In the article Aligning Items in a Flex Container we will explore these properties in more depth, in order to have a better understanding of how they work. These simple examples however will be useful in the majority of use cases.

Next steps

After reading this article you should have an understanding of the basic features of Flexbox. In the next article we will look at how this specification relates to other parts of CSS.