Flexbox

The CSS Podcast - 010: Flexbox

Um padrão de design que pode ser complicado no design responsivo é uma barra lateral que fica alinhada com algum conteúdo. Onde há espaço da janela de visualização, esse padrão funciona muito bem, mas onde o espaço é condensado, esse layout rígido pode se tornar problemático.

O modelo de layout de caixa flexível (flexbox) é um modelo de layout projetado para conteúdo unidimensional. Ela é excelente em pegar vários itens com tamanhos diferentes e retornar o melhor layout para eles.

Esse é o modelo de layout ideal para esse padrão de barra lateral. O Flexbox não apenas ajuda a posicionar a barra lateral e o conteúdo inline, mas, quando não há espaço suficiente, a barra lateral é dividida em uma nova linha. Em vez de definir dimensões rígidas para o navegador seguir, com o flexbox, você pode fornecer limites flexíveis para sugerir como o conteúdo pode ser exibido.

O que você pode fazer com um layout flexível?

Os layouts Flex têm os recursos abaixo, que você pode conhecer neste guia.

  • Eles podem ser exibidos como uma linha ou uma coluna.
  • Eles respeitam o modo de gravação do documento.
  • Elas são de linha única por padrão, mas podem ser solicitadas para serem exibidas em várias linhas.
  • Os itens do layout podem ser reorganizados visualmente no DOM.
  • O espaço pode ser distribuído dentro dos itens para que eles fiquem maiores e menores de acordo com o espaço disponível no pai.
  • O espaço pode ser distribuído ao redor dos itens e linhas flex em um layout unido, usando as propriedades de alinhamento de caixa.
  • Os itens podem ser alinhados no eixo transversal.

O eixo principal e o eixo transversal

A chave para entender o flexbox é entender o conceito de eixo principal e eixo cruzado. O eixo principal é o definido pela propriedade flex-direction. Se for row, o eixo principal está na linha. Se for column, o eixo principal está na coluna.

Três caixas uma ao lado da outra com uma seta apontando, apontando da esquerda para a direita. A seta é denominada Eixo principal

Os itens flexíveis se movem como um grupo no eixo principal. Lembre-se: temos muitas coisas e estamos tentando encontrar o melhor layout para elas como um grupo.

O eixo cruzado é executado na direção oposta ao eixo principal. Portanto, se flex-direction for row, o eixo cruzado será executado ao longo da coluna.

Três caixas de alturas diferentes, uma ao lado da outra, com uma seta apontando da esquerda para a direita. A seta é identificada como "Eixo principal". Há outra seta apontando de cima para baixo. Esta é chamada de eixo cruzado

Você pode fazer duas coisas no eixo transversal. É possível mover os itens individualmente ou em grupo, para que eles se alinhem entre si e com o contêiner flexível. Além disso, se você tiver linhas flexíveis agrupadas, é possível tratá-las como um grupo para controlar como o espaço é atribuído a elas. Você vai entender como tudo isso funciona na prática ao longo deste guia. Por enquanto, lembre-se de que o eixo principal segue sua flex-direction.

Como criar um contêiner flexível

Vamos conferir o comportamento do flexbox usando um grupo de itens de tamanhos diferentes e usando o flexbox para disponibilizá-los.

<div class="container" id="container">
  <div>One</div>
  <div>Item two</div>
  <div>The item we will refer to as three</div>
</div>

Para usar o Flexbox, é necessário declarar que você quer usar um contexto de formatação flexível e não um layout de bloco e inline regular. Para isso, mude o valor da propriedade display para flex.

.container {
  display: flex;
}

Como você aprendeu no guia de layout, isso vai gerar uma caixa no nível do bloco, com itens flexíveis filhos. Os itens Flex imediatamente começam a exibir algum comportamento de flexbox, usando seus valores iniciais.

Os valores iniciais significam que:

  • Os itens são mostrados como uma linha.
  • Eles não embalam.
  • Eles não crescem para preencher o contêiner.
  • Eles se alinham no início do contêiner.

Como controlar a direção dos itens

Mesmo que você ainda não tenha adicionado uma propriedade flex-direction, os itens aparecem como uma linha porque o valor inicial de flex-direction é row. Se você quiser uma linha, não é necessário adicionar a propriedade. Para mudar a direção, adicione a propriedade e um dos quatro valores:

  • row: os itens são dispostos em uma linha.
  • row-reverse: os itens são dispostos como uma linha do final do contêiner flexível.
  • column: os itens são dispostos como uma coluna.
  • column-reverse: os itens são dispostos como uma coluna no final do contêiner flexível.

Você pode testar todos os valores usando nosso grupo de itens na demonstração abaixo.

Como reverter o fluxo de itens e a acessibilidade

Tenha cuidado ao usar propriedades que reorganizem a exibição visual para longe de como as coisas são ordenadas no documento HTML, porque isso pode afetar negativamente a acessibilidade. Os valores row-reverse e column-reverse são um bom exemplo disso. A reordenação só acontece na ordem visual, não na ordem lógica. Isso é importante porque a ordem lógica é a ordem em que um leitor de tela vai ler o conteúdo, e qualquer pessoa que navegue usando o teclado vai seguir.

No vídeo a seguir, você pode conferir como, em um layout de linha invertido, a navegação por tabulação entre links fica desconectada, já que a navegação do teclado segue o DOM, e não a exibição visual.

Qualquer coisa que possa mudar a ordem dos itens no flexbox ou na grade pode causar esse problema. Portanto, qualquer reordenação precisa incluir testes completos para verificar se ela não dificulta o uso do site para algumas pessoas.

Para mais informações, acesse:

Modos de gravação e direção

Os itens flexíveis são dispostos como uma linha por padrão. Uma linha é executada na direção em que as frases fluem no modo de escrita e na direção do script. Isso significa que, se você estiver trabalhando em árabe, que tem uma direção de script da direita para a esquerda (rtl), os itens serão alinhados à direita. A ordem das guias também começa à direita, porque é assim que as frases são lidas em árabe.

Se você estiver trabalhando com um modo de escrita vertical, como alguns tipos de letra japoneses, uma linha será executada verticalmente, de cima para baixo. Tente mudar a flex-direction nesta demonstração, que está usando um modo de gravação vertical.

Portanto, a forma como os itens flexíveis se comportam por padrão está vinculada ao modo de escrita do documento. A maioria dos tutoriais é escrita em inglês ou outro modo de escrita horizontal da esquerda para a direita. Isso facilita presumir que os itens flexíveis estão alinhados à esquerda e executados na horizontal.

Com o eixo principal e cruzado, além do modo de gravação a ser considerado, o fato de falarmos sobre início e fim em vez de cima, baixo, esquerda e direita em flexbox pode ser mais fácil de entender. Cada eixo tem um início e um fim. O início do eixo principal é chamado de main-start. Os itens flexíveis são alinhados inicialmente a partir do início principal. O fim desse eixo é main-end. O início do eixo cruzado é cross-start e o fim é cross-end.

Um diagrama rotulado dos termos acima

Unir itens flex

O valor inicial da propriedade flex-wrap é nowrap. Isso significa que, se não houver espaço suficiente no contêiner, os itens vão estourar.

Um contêiner flexível com nove itens dentro dele, os itens foram reduzidos para que uma palavra ficasse em uma linha,
mas não há espaço suficiente para mostrar os itens lado a lado, então os itens flexíveis foram estendidos para fora da
caixa do contêiner.
Quando eles atingirem o tamanho mínimo de conteúdo, os itens flexíveis começarão a transbordar do contêiner.

Os itens exibidos com os valores iniciais serão reduzidos o mínimo possível, até o tamanho de min-content antes do estouro.

Para fazer com que os itens sejam unidos, adicione flex-wrap: wrap ao contêiner flexível.

.container {
  display: flex;
  flex-wrap: wrap;
}

Quando um contêiner flexível é encapsulado, ele cria várias linhas flexíveis. Em termos de distribuição de espaço, cada linha funciona como um novo contêiner flexível. Portanto, se você estiver agrupando linhas, não será possível alinhar algo na linha 2 com algo acima dela na linha 1. É por isso que o flexbox é unidimensional. É possível controlar o alinhamento em um eixo, linha ou coluna, não em ambos ao mesmo tempo, como fazemos na grade.

Abreviação de fluxo flexível

É possível definir as propriedades flex-direction e flex-wrap usando a abreviação flex-flow. Por exemplo, para definir flex-direction como column e permitir que os itens sejam agrupados:

.container {
  display: flex;
  flex-flow: column wrap;
}

Como controlar o espaço dentro de itens flexíveis

Supondo que nosso contêiner tenha mais espaço do que o necessário para exibir os itens, os itens são alinhados no início e não crescem para preencher o espaço. Elas param de crescer no tamanho máximo de conteúdo. Isso ocorre porque o valor inicial das propriedades flex- é:

  • flex-grow: 0: os itens não crescem.
  • flex-shrink: 1: os itens podem encolher mais do que o flex-basis.
  • flex-basis: auto: os itens têm um tamanho base de auto.

Isso pode ser representado por um valor de palavra-chave de flex: initial. A propriedade abreviada flex ou as longhands de flex-grow, flex-shrink e flex-basis são aplicadas aos filhos do contêiner flexível.

Para fazer com que os itens cresçam, permitindo que os itens grandes tenham mais espaço do que os pequenos, use flex:auto. Você pode testar isso usando a demonstração acima. Isso define as propriedades como:

  • flex-grow: 1: os itens podem crescer mais do que o flex-basis.
  • flex-shrink: 1: os itens podem encolher para um tamanho menor que o flex-basis.
  • flex-basis: auto: os itens têm um tamanho base de auto.

O uso de flex: auto significa que os itens vão ter tamanhos diferentes, já que o espaço compartilhado entre eles é dividido depois de cada item ser disposto como tamanho máximo de conteúdo. Assim, um item grande vai ganhar mais espaço. Para forçar todos os itens a ter um tamanho consistente e ignorar o tamanho do conteúdo, mude flex:auto para flex: 1 na demonstração.

Isso é descompactado para:

  • flex-grow: 1: os itens podem ultrapassar a flex-basis.
  • flex-shrink: 1: os itens podem ser reduzidos para menos do que flex-basis.
  • flex-basis: 0: os itens têm um tamanho base de 0.

O uso de flex: 1 indica que todos os itens têm tamanho zero, portanto, todo o espaço no contêiner flexível está disponível para distribuição. Como todos os itens têm um fator flex-grow de 1, todos crescem igualmente e o espaço é compartilhado igualmente.

Permitir que os itens cresçam em taxas diferentes

Não é necessário atribuir a todos os itens um fator flex-grow de 1. Você pode atribuir diferentes fatores flex-grow aos itens flexíveis. Na demonstração abaixo, o primeiro item tem flex: 1, o segundo flex: 2 e o terceiro flex: 3. À medida que esses itens crescem de 0, o espaço disponível no contêiner flexível é dividido em seis. Uma parte é dada ao primeiro item, duas partes ao segundo e três partes ao terceiro.

Você pode fazer a mesma coisa com um flex-basis de auto, mas precisará especificar os três valores. O primeiro valor é flex-grow, o segundo é flex-shrink e o terceiro é flex-basis.

.item1 {
  flex: 1 1 auto;
}

.item2 {
  flex: 2 1 auto;
}

Esse é um caso de uso menos comum, porque o motivo para usar um flex-basis de auto é permitir que o navegador descubra a distribuição de espaço. No entanto, isso pode ser útil caso você queira fazer com que um item cresça um pouco mais do que o algoritmo decide.

Como reordenar itens flexíveis

Os itens no seu contêiner flexível podem ser reordenados usando a propriedade order. Essa propriedade permite ordenar itens em grupos ordinais. Os itens são dispostos na direção determinada por flex-direction, com os valores mais baixos em primeiro lugar. Se mais de um item tiver o mesmo valor, ele será mostrado com os outros itens com esse valor.

O exemplo abaixo demonstra essa ordem.

Teste seu conhecimento

Teste seus conhecimentos sobre o flexbox

O flex-direction padrão é

row
Por padrão, o flexbox ajusta os itens em uma linha, alinhando-os no início. Com o wrapper ativado, ele continuará criando linhas para que os filhos fluam.
column
Definir flex-direction como coluna é uma ótima maneira de empilhar elementos, mas não é o valor padrão.

Por padrão, um contêiner flexível encapsula os filhos.

verdadeiro
A delimitação precisa estar ativada.
falso
Use flex-wrap: wrap com display: flex para agrupar filhos

Um item filho flexível aparece apertado. Qual propriedade flexível ajuda a minimizar isso?

flex-grow
Essa propriedade descreve se os elementos podem crescer além de um tamanho básico, não como eles se comportam com base nele.
flex-shrink
Sim, essa propriedade descreve como processar o dimensionamento se a largura estiver abaixo da base.
flex-basis
Isso fornece o ponto de partida do dimensionamento, mas não como lidar com cenários de dimensionamento em que a largura fica abaixo da base, como em um cenário comprimido.

Visão geral do alinhamento do Flexbox

O Flexbox trouxe um conjunto de propriedades para alinhar itens e distribuir espaço entre eles. Essas propriedades foram tão úteis que foram movidas para a própria especificação. Você também vai encontrar essas propriedades no layout de grade. Aqui você pode descobrir como eles funcionam quando você usa o flexbox.

O conjunto de propriedades pode ser colocado em dois grupos. Propriedades para distribuição de espaço e propriedades para alinhamento. As propriedades que distribuem o espaço são:

  • justify-content: distribuição de espaço no eixo principal.
  • align-content: distribuição de espaço no eixo transversal.
  • place-content: uma abreviação para definir as duas propriedades acima.

As propriedades usadas para alinhamento no flexbox:

  • align-self: alinha um único item na eixo transversal.
  • align-items: alinha todos os itens como um grupo no eixo transversal.

Se você estiver trabalhando no eixo principal, as propriedades começam com justify-. No eixo transversal, começam com align-.

Como distribuir o espaço no eixo principal

Com o HTML usado anteriormente, os itens flexíveis foram dispostos como uma linha, e há espaço no eixo principal. Os itens não são grandes o suficiente para preencher completamente o contêiner flexível. Os itens são alinhados no início do contêiner flexível porque o valor inicial de justify-content é flex-start. Os itens aparecem no início e qualquer espaço extra fica no final.

Adicione a propriedade justify-content ao contêiner flexível, atribua um valor de flex-end, e os itens serão alinhados no final do contêiner, e o espaço extra será colocado no início.

.container {
  display: flex;
  justify-content: flex-end;
}

Também é possível distribuir o espaço entre os itens com justify-content: space-between.

Teste alguns dos valores na demonstração e consulte o MDN para conferir o conjunto completo de valores possíveis.

Com flex-direction: column

Se você tiver mudado flex-direction para column, justify-content vai funcionar na coluna. Para ter espaço extra no contêiner ao trabalhar como uma coluna, você precisa atribuir um height ou block-size a ele. Caso contrário, você não terá espaço extra para distribuir.

Teste os valores diferentes, desta vez com um layout de coluna flexbox.

Distribuição de espaço entre linhas flexíveis

Com um contêiner flexível envolvido, você pode ter espaço para distribuir no eixo cruzado. Nesse caso, você pode usar a propriedade align-content com os mesmos valores de justify-content. Ao contrário de justify-content, que alinha os itens a flex-start por padrão, o valor inicial de align-content é stretch. Adicione a propriedade align-content ao contêiner flexível para alterar esse comportamento padrão.

.container {
  align-content: center;
}

Teste isso na demonstração. O exemplo tem linhas de itens flexíveis, e o contêiner tem um block-size para que tenhamos algum espaço extra.

A abreviação place-content

Para definir justify-content e align-content, use place-content com um ou dois valores. Um único valor será usado para os dois eixos, se você especificar os dois, o primeiro será usado para align-content e o segundo para justify-content.

.container {
  place-content: space-between;
  /* sets both to space-between */
}

.container {
  place-content: center flex-end;
  /* wrapped lines on the cross axis are centered,
  on the main axis items are aligned to the end of the flex container */
}

Alinhar itens no eixo transversal

No eixo cruzado, você também pode alinhar seus itens na linha flexível usando align-items e align-self. O espaço disponível para esse alinhamento vai depender da altura do contêiner flexível ou da linha flexível no caso de um conjunto de itens agrupados.

O valor inicial de align-self é stretch, por isso os itens flexíveis em uma linha se estendem até a altura do item mais alto por padrão. Para mudar isso, adicione a propriedade align-self a qualquer um dos itens flexíveis.

.container {
  display: flex;
}

.item1 {
  align-self: flex-start;
}

Use um dos seguintes valores para alinhar o item:

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

Consulte a lista completa de valores no MDN.

A próxima demonstração tem uma única linha de itens flexíveis com flex-direction: row. O último item define a altura do contêiner flexível. O primeiro item tem a propriedade align-self com um valor de flex-start. Tente mudar o valor dessa propriedade para ver como ela se move no espaço no eixo cruzado.

A propriedade align-self é aplicada a itens individuais. A propriedade align-items pode ser aplicada ao contêiner flexível para definir todas as propriedades align-self individuais como um grupo.

.container {
  display: flex;
  align-items: flex-start;
}

Nesta próxima demonstração, tente mudar o valor de align-items para alinhar todos os itens no eixo cruzado como um grupo.

Por que não há justificativa para si mesmo no flexbox?

Os itens flexíveis funcionam como um grupo no eixo principal. Portanto, não há o conceito de dividir um item individual fora desse grupo.

No layout de grade, as propriedades justify-self e justify-items funcionam no eixo inline para alinhar itens nesse eixo dentro da área da grade. Devido à forma como os layouts flexíveis tratam os itens como um grupo, essas propriedades não são implementadas em um contexto flexível.

Vale a pena saber que o flexbox funciona muito bem com margens automáticas. Se você precisar dividir um item de um grupo ou separar o grupo em dois, aplique uma margem para isso. No exemplo abaixo, o último item tem uma margem esquerda de auto. A margem automática absorve todo o espaço na direção em que é aplicada. Isso significa que ele empurra o item para a direita, dividindo os grupos.

Como centralizar um item na vertical e na horizontal

As propriedades de alinhamento podem ser usadas para centralizar um item dentro de outra caixa. A propriedade justify-content alinha o item no eixo principal, que é a linha. A propriedade align-items no eixo cruzado.

.container {
  width: 400px;
  height: 300px;
  display: flex;
  justify-content: center;
  align-items: center;
}

Teste seu conhecimento

Teste seus conhecimentos sobre flexbox

.container {
  display: flex;
  direction: ltr;
}

Para alinhar verticalmente com o flexbox, use

alinhar palavras-chave
Legal
justificar palavras-chave
Desculpe
.container {
  display: flex;
  direction: ltr;
}

Para alinhar horizontalmente com o flexbox, use

alinhar palavras-chave
Desculpe
justificar palavras-chave
Legal
.container {
  display: flex;
  direction: ltr;
}

Por padrão, os itens flexíveis são alinhados a stretch. Se você quiser que o tamanho do conteúdo seja usado para itens filhos, qual dos estilos a seguir você usaria?

justify-content: flex-start
A propriedade "justify" é para alinhamento horizontal, não vertical.
align-content: start
content alinha linhas flexíveis, não o alinhamento de itens filhos.
height: auto
Isso não vai ter efeito.
align-items: flex-start
Sim, queremos alinhá-los verticalmente à "parte de cima" ou à parte inicial, o que remove o valor de alongamento padrão e usa a altura do conteúdo.

Recursos