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.
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.
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.
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.
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 oflex-basis
.flex-basis: auto
: os itens têm um tamanho base deauto
.
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 oflex-basis
.flex-shrink: 1
: os itens podem encolher para um tamanho menor que oflex-basis
.flex-basis: auto
: os itens têm um tamanho base deauto
.
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 aflex-basis
.flex-shrink: 1
: os itens podem ser reduzidos para menos do queflex-basis
.flex-basis: 0
: os itens têm um tamanho base de0
.
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 é
column
row
Por padrão, um contêiner flexível encapsula os filhos.
Um item filho flexível aparece apertado. Qual propriedade flexível ajuda a minimizar isso?
flex-shrink
flex-basis
flex-grow
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
.container { display: flex; direction: ltr; }
Para alinhar horizontalmente com o flexbox, use
.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?
align-content: start
height: auto
justify-content: flex-start
align-items: flex-start
Recursos
- O MDN CSS Flexible Box Layout (link em inglês) inclui uma série de guias detalhados com exemplos.
- Guia de truques de CSS para Flexbox
- O que acontece quando você cria um contêiner flexível de Flexbox
- Tudo o que você precisa saber sobre o alinhamento no Flexbox
- Qual o tamanho do box flexível?
- Casos de uso do Flexbox
- Inspecionar e depurar layouts CSS Flexbox no Chrome DevTools