Flexbox

Podcast do CSS - 010: Flexbox

Um padrão de design que pode ser complicado no design responsivo é uma barra lateral alinhada com algum conteúdo. Onde há espaço da janela de visualização, esse padrão funciona muito bem, mas quando o espaço é condensado, o layout rígido pode ser 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 só ajuda a posicionar a barra lateral e o conteúdo inline, mas quando não houver espaço suficiente, a barra lateral vai ser quebrada 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 a seguir, que você poderá explorar neste guia.

  • Eles podem aparecer como uma linha ou coluna.
  • Elas respeitam o modo de escrita do documento.
  • Por padrão, eles são de uma única linha, mas podem ser solicitados para serem quebrados em várias linhas.
  • Os itens no layout podem ser reordenados visualmente, fora da ordem no DOM.
  • O espaço pode ser distribuído dentro dos itens, para que eles se tornem 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 das linhas flexíveis em um layout encapsulado, usando as propriedades de alinhamento de caixa.
  • Os próprios itens podem ser alinhados no eixo cruzado.

Eixo principal e eixo cruzado

A chave para entender o flexbox é entender os conceitos de eixo principal e eixo cruzado. O eixo principal é aquele definido pela propriedade flex-direction. Se for row, o eixo principal estará ao longo da linha. Se for column, o eixo principal estará ao longo da coluna.

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

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

O eixo cruzado é executado na outra direção em relação ao eixo principal. Se flex-direction for row, o eixo cruzado vai ao longo da coluna.

Três caixas de alturas diferentes, lado a lado com uma seta, apontando da esquerda para a direita. A seta é identificada como "Eixo principal". Há outra seta apontando de cima para baixo. Este item tem o rótulo "Eixo cruzado"

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

Como criar um contêiner flexível

Para ver como o flexbox se comporta, use um grupo de itens de tamanhos diferentes e use o flexbox para dispor os itens.

<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 in-line e de bloco normal. Para isso, altere o valor da propriedade display para flex.

.container {
  display: flex;
}

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

Os valores iniciais significam que:

  • Os itens são mostrados em uma linha.
  • Eles não se unem.
  • Elas não crescem para preencher o contêiner.
  • Eles ficam alinhados 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 serão mostrados como uma linha, porque o valor inicial de flex-direction é row. Se você quiser uma linha, não vai precisar adicionar a propriedade. Para mudar a direção, adicione a propriedade e um dos quatro valores:

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

Teste todos os valores usando nosso grupo de itens na demonstração abaixo.

Reversão do fluxo de itens e da acessibilidade

Tenha cuidado ao usar propriedades que reordenam a exibição visual fora da ordem 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 acontece apenas para a ordem visual, não para a ordem lógica. É importante entender isso, já que 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 essa ordem.

Veja no vídeo a seguir como, em um layout de linha invertido, a guia entre links se desconecta à medida que a navegação pelo 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 não vai dificultar o uso do site para algumas pessoas.

Para mais informações, veja:

Modos e direção de escrita

Por padrão, os itens flexíveis são dispostos em uma linha. Uma linha é executada na direção que as frases fluem em seu modo de escrita e direção de 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 de tabulação 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 algumas famílias tipográficas japonesas, uma linha será executada verticalmente, de cima para baixo. Tente mudar o flex-direction nesta demonstração que está usando o modo de gravação vertical.

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

Considerando os eixos principal e transversal e o modo de escrita, o fato de falarmos sobre start e end em vez de cima, de baixo, da esquerda e da direita no 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. Então, nossos itens flexíveis inicialmente se alinham do main-start. O final desse eixo é main-end. O início do eixo cruzado é cross-start, e o final é cross-end.

Um diagrama com rótulos dos termos acima

Como unir itens flexíveis

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 esteja em uma linha,
mas não há espaço suficiente para mostrá-los lado a lado. Assim, os itens flexíveis se estenderam para fora
da caixa do contêiner.
Quando atingem o tamanho mínimo de conteúdo, os itens flexíveis começam a ultrapassar o contêiner.

Os itens exibidos usando os valores iniciais vão ser reduzidos o máximo possível, até o tamanho de min-content antes que ocorra o 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 atua como um novo contêiner flexível. Portanto, se você estiver quebrando linhas, não será possível alinhar algo da linha 2 com algo acima dela na linha 1. Isso é o que significa o flexbox ser unidimensional. É possível controlar o alinhamento em um eixo, em uma linha ou em uma coluna, não em ambos juntos, como podemos fazer na grade.

A abreviação flexflow

É 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 o contêiner tenha mais espaço do que o necessário para mostrar os itens, eles ficam enfileirados no início e não crescem para preencher o espaço. Eles param de crescer com o 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 ser reduzidos para menos que seu 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 os longos de flex-grow, flex-shrink e flex-basis, são aplicados aos filhos do contêiner flexível.

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

  • flex-grow: 1: os itens podem ultrapassar o flex-basis.
  • flex-shrink: 1: os itens podem ser menores que o flex-basis.
  • flex-basis: auto: os itens têm um tamanho base de auto.

Usar flex: auto significa que os itens têm tamanhos diferentes, já que o espaço compartilhado entre os itens é compartilhado depois que cada item é definido como tamanho máximo de conteúdo. Portanto, um item grande vai ocupar 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.

Ele é descompactado para:

  • flex-grow: 1: os itens podem ultrapassar o flex-basis.
  • flex-shrink: 1: os itens podem ser menores que o flex-basis.
  • flex-basis: 0: os itens têm um tamanho base de 0.

O uso de flex: 1 informa 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 de 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. É possível 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 é compartilhado em seis. Uma parte é dada ao primeiro item, duas partes para o segundo e três partes para o terceiro.

Você pode fazer o mesmo em um flex-basis de auto, embora precise 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 é para permitir que o navegador descubra a distribuição do espaço. Se você quiser fazer com que um item cresça um pouco mais do que o algoritmo decide, de maneira útil.

Como reordenar itens flexíveis

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

O exemplo abaixo demonstra essa ordem.

Teste seu conhecimento

Teste seus conhecimentos sobre flexbox

O flex-direction padrão é

row
Por padrão, o flexbox encaixa os itens em uma linha, alinhando-os no início. Com o wrapper ativado, ele continuará criando linhas para que os filhos fluam dentro delas.
column
Definir a direção flexível 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.
false
Usar flex-wrap: wrap com display: flex para unir filhos

Um item filho flexível aparece amassado. Qual propriedade flexível ajuda a minimizar esse problema?

flex-grow
Esta propriedade descreve se os elementos podem crescer além de um tamanho de base, não como eles devem se comportar.
flex-shrink
Sim, essa propriedade descreve como processar o tamanho 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 reduzido.

Visão geral do alinhamento do Flexbox

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

O conjunto de propriedades pode ser dividido em dois grupos. Propriedades para distribuição do 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 cruzado.
  • place-content: uma abreviação para definir as duas propriedades acima.

Propriedades usadas para alinhamento em flexbox:

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

Se você estiver trabalhando no eixo principal, as propriedades vão começar com justify-. No eixo cruzado, eles começam com align-.

Distribuição de espaço no eixo principal

Com o HTML usado anteriormente, os itens flexíveis dispostos como uma linha, 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 ficam alinhados no início do contêiner flexível porque o valor inicial de justify-content é flex-start. Os itens ficam alinhados no início, e qualquer espaço extra fica no final.

Adicione a propriedade justify-content ao contêiner flexível, atribua a ele o valor de flex-end e os itens se alinham no final do contêiner e o espaço extra é colocado no início.

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

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

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

Com flex-direction: column

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

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

Distribuir espaço entre as linhas flexíveis

Com um contêiner flexível encapsulado, pode haver espaço para distribuir no eixo cruzado. Nesse caso, é possível usar a propriedade align-content com os mesmos valores que 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 mudar esse comportamento padrão.

.container {
  align-content: center;
}

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

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 que o primeiro seja 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 */
}

Alinhamento de itens no eixo cruzado

No eixo cruzado, também é possível alinhar seus itens dentro da 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 unidos.

O valor inicial de align-self é stretch. É por isso que os itens flexíveis de uma linha se esticam 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

Veja 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 alterar o valor dessa propriedade para ver como ela se move dentro de seu 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;
}

Na 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á uma justificativa no flexbox?

Itens flexíveis atuam como um grupo no eixo principal. Portanto, não há conceito de dividir um item individual nesse grupo.

No layout de grade, as propriedades justify-self e justify-items funcionam no eixo inline para fazer o alinhamento de itens nesse eixo dentro da área de grade. Devido à maneira 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 separar um item de um grupo ou separar o grupo em dois, aplique uma margem para fazer 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 vertical e horizontalmente

As propriedades de alinhamento podem ser usadas para centralizar um item dentro de outra caixa. A propriedade justify-content alinha o item ao 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 flexbox, use

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

Por padrão, os itens flexíveis estão alinhados a stretch. Se você quisesse que o tamanho do conteúdo fosse usado em 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 terá efeito.
align-items: flex-start
Sim, queremos alinhá-los verticalmente ao 'topo' ou início, o que remove o valor padrão de esticar e usa a altura do conteúdo.

Recursos