Skip to content
This page has been auto-translated and may contain errors.View in English

Flexbox ​

Você quer três botões em uma linha, espaçados uniformemente, todos com a mesma altura, e centralizados verticalmente não importa quanto texto cada um contenha. Antigamente isso significava floats, clearfixes e muita tentativa e erro. O flexbox é a ferramenta criada exatamente para isso: você diz a um container para organizar seus filhos em linha, e depois ajusta a posição deles ao longo de dois eixos até que fiquem onde você quer. Boa parte do layout que você vê pela web no dia a dia, barras de navegação, barras de ferramentas, fileiras de cards, é um flex container por baixo dos panos.

O flex container ​

O flexbox começa com uma única linha aplicada a um elemento pai. Defina display: flex em um container e seus filhos diretos se alinham em linha, um ao lado do outro. Esse container agora é um flex container, e cada filho dentro dele se torna um flex item.

css
.nav {
  display: flex;    /* os filhos agora ficam em linha */
}

Os itens se organizam ao longo de duas direções. O eixo principal vai da esquerda para a direita, na direção em que os itens se alinham. O eixo transversal vai de cima para baixo, cruzando a linha. Você vai posicionar os itens usando esses dois eixos, então já vale a pena visualizá-los agora: o eixo principal é a linha em que os itens se apoiam, o eixo transversal é a direção que a atravessa.

display: flex transforma um elemento em um flex container e seus filhos diretos em flex items. Só os filhos diretos participam; qualquer coisa aninhada mais profundamente é organizada pelo próprio pai dela. Por padrão os itens ficam em linha, da esquerda para a direita, cada um encolhido até a largura do seu conteúdo.

css
.nav {
  display: flex;    /* filhos diretos se tornam uma linha de flex items */
}

Todo o modelo funciona sobre dois eixos. O eixo principal é a direção em que os itens fluem, uma linha por padrão, ou seja, da esquerda para a direita. O eixo transversal é perpendicular a ele, indo de cima para baixo. Toda propriedade de alinhamento que você encontrar atua em um eixo ou no outro, então manter os dois bem definidos na cabeça é o que faz o resto se encaixar.

display: flex dá a um elemento um contexto de formatação flex: seus filhos diretos se tornam flex items e são organizados pelo algoritmo do flex em vez do fluxo normal. Só os filhos diretos participam; trechos de texto e descendentes aninhados são tratados abaixo deles. Esse é o mesmo tipo de limite que impede o colapso de margens, e é uma das razões pelas quais os layouts flex se comportam de forma mais previsível do que a era dos floats e clears que eles substituíram.

css
.nav {
  display: flex;    /* estabelece um contexto de formatação flex */
}

Dois eixos governam tudo. O eixo principal é definido por flex-direction (uma linha por padrão, ou seja, do início ao fim em linha), e o eixo transversal é perpendicular a ele. Essa distinção não é só cosmética: justify-content sempre age ao longo do eixo principal e align-items sempre age ao longo do eixo transversal, então no momento em que você muda flex-direction para column, essas duas propriedades trocam a direção em que empurram os itens. Nomear o layout pelo eixo, em vez de por "horizontal" e "vertical", é o que mantém tudo coerente quando a direção muda.

css
.nav {
  display: flex;
}

Uma única declaração, e os filhos de qualquer bloco deixam de se empilhar de cima para baixo e passam a ficar em linha. Todo o resto deste capítulo é sobre como direcionar esses itens depois que eles estão dentro do container.

JunoO flex container Coloque display: flex em um pai e seus filhos diretos se alinham em linha. Esse pai é o flex container, os filhos são os flex items. Os itens se movem ao longo de duas direções: o eixo principal é a linha em que eles se apoiam, o eixo transversal a atravessa, e você vai posicionar itens usando os dois.
JunoO flex containerdisplay: flex faz um container organizar seus filhos diretos como uma linha de flex items. Só os filhos diretos participam, não o que estiver aninhado mais profundamente. Mantenha os dois eixos claros na cabeça: o eixo principal é a direção do fluxo, o eixo transversal é perpendicular a ele, e toda propriedade de alinhamento atua em um ou no outro.
JunoO flex containerdisplay: flex inicia um contexto de formatação flex, então os filhos diretos são organizados pelo algoritmo do flex e as margens deixam de colapsar ali dentro. Nomeie o layout pelo eixo, não por horizontal e vertical, porque justify-content acompanha o eixo principal e align-items o eixo transversal. Mude flex-direction para column e essas duas trocam a direção em que empurram.

Alinhando ao longo dos eixos ​

Depois que seus itens estão em linha, duas propriedades os movem de um lado para o outro. justify-content espaça os itens ao longo do eixo principal, a direção em que eles se apoiam. align-items os move ao longo do eixo transversal, para cima e para baixo dentro da linha.

css
.nav {
  display: flex;
  justify-content: space-between;   /* afasta os itens ao longo da linha */
  align-items: center;              /* alinha eles no meio vertical */
}

Os valores mais comuns de justify-content são flex-start (agrupados à esquerda), center (agrupados no meio), flex-end (agrupados à direita), space-between (espaços entre os itens, nenhum nas pontas) e space-around (espaços de ambos os lados de cada item). Para align-items, center é o valor que você mais vai usar.

Para centralizar algo nos dois sentidos, o truque que todo mundo aprende primeiro: defina os dois como center.

css
.hero {
  display: flex;
  justify-content: center;   /* centralizado ao longo do eixo principal */
  align-items: center;       /* centralizado ao longo do eixo transversal */
}

Duas propriedades cuidam do alinhamento, uma para cada eixo. justify-content distribui os itens ao longo do eixo principal, e align-items os posiciona no eixo transversal. Como cada uma cuida de um eixo diferente, elas nunca entram em conflito, apontam em direções perpendiculares.

css
.nav {
  display: flex;
  justify-content: space-between;   /* distribui os itens ao longo do eixo principal */
  align-items: center;              /* centraliza eles no eixo transversal */
}

Para justify-content, os valores que vale a pena conhecer são flex-start, center, flex-end, space-between (espaços iguais entre os itens, encostados nas bordas) e space-around (espaço igual em volta de cada item, então os espaços das pontas ficam com metade do tamanho dos do meio). Para align-items, o padrão é stretch, que faz cada item preencher toda a altura do container, e é por isso que uma fileira de cards sai com a mesma altura mesmo quando o conteúdo é diferente. Defina align-items: center e eles voltam a encolher até a altura do próprio conteúdo e ficam no meio em vez disso.

Centralizar nos dois eixos é a dupla de propriedades que fez o flexbox famoso:

css
.hero {
  display: flex;
  justify-content: center;   /* eixo principal */
  align-items: center;       /* eixo transversal */
}

O alinhamento se divide claramente por eixo. justify-content distribui o espaço livre ao longo do eixo principal, e align-items define a posição padrão de cada item no eixo transversal. Elas não podem entrar em conflito porque operam em eixos perpendiculares, mas as duas dependem de qual direção é a "principal", então um flex-direction: column troca o que cada uma controla.

css
.nav {
  display: flex;
  justify-content: space-between;   /* o espaço livre vai entre os itens */
  align-items: center;              /* cada item centralizado no eixo transversal */
}

O detalhe que costuma confundir é que justify-content só tem algo a fazer quando existe espaço sobrando no eixo principal. Ela distribui espaço livre, então, se os itens já preenchem o container (ou o extrapolam), space-between e center parecem idênticos porque não há nada para distribuir. align-items, por outro lado, posiciona cada item de forma independente dentro do tamanho transversal do container, e seu valor inicial é stretch: itens sem um tamanho fixo no eixo transversal crescem até preencher o container. A fileira de cards com altura igual é o align-items: stretch fazendo seu trabalho padrão. Sobrescreva isso item a item com align-self, tratado na seção de dimensionamento mais abaixo.

css
.hero {
  display: flex;
  justify-content: center;   /* centralização no eixo principal */
  align-items: center;       /* centralização no eixo transversal, sobrescreve o padrão stretch */
}

Dois itens e um min-height no container, ambos definidos como center, e você resolveu o problema de centralização que levou uma geração de desenvolvedores a fingir com positioning absoluto e margens negativas.

JunoAlinhando ao longo dos eixosjustify-content espaça os itens ao longo do eixo principal, align-items os move ao longo do eixo transversal. Os valores para lembrar do primeiro são center, space-between e flex-start. Defina os dois como center e o que estiver dentro fica exatamente no meio, um truque de layout que você vai usar repetidamente.
JunoAlinhando ao longo dos eixos Uma propriedade para cada eixo: justify-content no eixo principal, align-items no transversal. O padrão align-items: stretch é o motivo de uma fileira de cards sair com a mesma altura sem você precisar pedir. E os dois definidos como center é o truque para centralizar qualquer coisa que vale a pena guardar de cabeça.
JunoAlinhando ao longo dos eixosjustify-content distribui o espaço sobrando no eixo principal, então, se os itens já preenchem a linha, ela não faz nada, o que explica muitos momentos de "por que isso não está centralizando". align-items posiciona cada item no eixo transversal e assume stretch por padrão, dando fileiras de altura igual de graça. Mude flex-direction e lembre-se de que as duas propriedades trocam o eixo em que atuam.

Direção e quebra de linha ​

Por padrão, um flex container organiza os itens em linha. Mude isso com flex-direction. Defina como column e os itens se empilham de cima para baixo em vez de ficarem lado a lado.

css
.sidebar {
  display: flex;
  flex-direction: column;   /* os itens agora se empilham verticalmente */
}

Quando os itens em linha ficam sem espaço, eles vão sendo espremidos cada vez mais finos. Para deixar que caiam para uma nova linha em vez disso, adicione flex-wrap: wrap.

css
.card-row {
  display: flex;
  flex-wrap: wrap;   /* itens que não cabem passam para a próxima linha */
}

Para o espaço entre os itens, use gap. Ele adiciona um espaço uniforme entre cada item sem adicionar espaço nas bordas externas.

css
.card-row {
  display: flex;
  gap: 16px;   /* 16px entre cada item */
}

flex-direction define o eixo principal. O padrão row vai da esquerda para a direita; column torna o eixo principal vertical, então os itens se empilham de cima para baixo e, o mais importante, justify-content agora controla o espaçamento vertical enquanto align-items controla o horizontal. Também existem row-reverse e column-reverse, se você precisar inverter a ordem.

css
.sidebar {
  display: flex;
  flex-direction: column;   /* o eixo principal agora é vertical */
  justify-content: center;  /* o que significa que isso centraliza verticalmente */
}

Por padrão, uma linha flex nunca quebra: os itens encolhem para caber em vez de quebrar linha. Defina flex-wrap: wrap e os itens que não cabem passam para uma nova linha, o que é o que torna possível uma grade de cards responsiva sem media queries.

css
.card-row {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;   /* gap funciona nos dois eixos: 16px entre linhas e colunas */
}

Use gap para espaçamento, não margens nos itens. gap se aplica só entre os itens, nunca nas bordas externas, então você nunca precisa remover uma margem sobrando do último filho.

flex-direction define o eixo principal, e toda propriedade que depende de eixo segue essa definição. row (o padrão) torna o eixo principal horizontal; column o torna vertical e, silenciosamente, reatribui justify-content ao espaçamento vertical e align-items ao horizontal. As variantes com -reverse invertem a direção do eixo principal, mas note que elas só reordenam visualmente: a ordem no DOM permanece a mesma, então a ordem de navegação por teclado e leitores de tela continua seguindo a fonte, algo que é uma consideração real de acessibilidade quando você recorre a row-reverse.

css
.sidebar {
  display: flex;
  flex-direction: column;    /* eixo principal vertical; justify-content agora centraliza verticalmente */
  gap: 8px;
}

flex-wrap: wrap remove a restrição de linha única. Sem ele, um flex container força todos os itens para uma única linha e distribui qualquer falta de espaço encolhendo-os; com ele, itens que extrapolam o tamanho principal quebram para novas linhas, e o container passa a ter múltiplas linhas. Uma vez que a quebra está ativada, align-content (diferente de align-items) governa como as linhas são espaçadas no eixo transversal. gap define o espaço entre os itens e, quando há quebra, entre as linhas, e é a ferramenta correta: diferente das margens, ela não colapsa nada, não adiciona espaço nas bordas, e representa uma única decisão de espaçamento.

css
.card-row {
  display: flex;
  flex-wrap: wrap;
  gap: 16px 24px;   /* row-gap 16px, column-gap 24px */
}

É aqui também que aparece o limite com o CSS grid. O flex wrap preenche uma linha e depois quebra, então os itens em linhas diferentes não se alinham em colunas. Quando você precisa de uma grade verdadeiramente bidimensional com linhas e colunas alinhadas, esse é o trabalho do grid, não do flexbox.

JunoDireção e quebra de linhaflex-direction: column empilha os itens verticalmente em vez de em linha. flex-wrap: wrap deixa os itens caírem para uma nova linha quando o espaço acaba, em vez de serem espremidos. E gap coloca espaço uniforme entre os itens sem adicionar nada nas bordas, então use ele antes de recorrer a margens.
JunoDireção e quebra de linhaflex-direction define o eixo principal, e mudar para column significa que justify-content agora espaça verticalmente, o que surpreende as pessoas uma vez na vida. flex-wrap: wrap é o que faz uma fileira de cards se reorganizar sem media queries. Use gap para espaçamento, assim você nunca precisa caçar uma margem perdida no último item.
JunoDireção e quebra de linhaflex-direction define o eixo principal e toda propriedade baseada em eixo segue essa definição, enquanto os valores com -reverse reordenam visualmente mas deixam a ordem do DOM e do foco intactas, então use-os com cuidado. flex-wrap torna um container multilinha e passa o espaçamento entre linhas para align-content. Quando itens quebrados precisam se alinhar em colunas de verdade, isso é grid, não flexbox.

Dimensionamento flexível dos itens ​

O ponto central do flexbox é que os itens podem flexionar, crescendo ou encolhendo para dividir o espaço. O atalho que você vai usar mais é flex: 1 em um item, que diz a ele para crescer e ocupar uma fração igual de todo espaço disponível.

css
.card {
  flex: 1;   /* cada card cresce para preencher uma fração igual da linha */
}

Coloque flex: 1 em três cards em linha e eles dividem o container em três larguras iguais. Dê a um card flex: 2 e ele ocupa o dobro do espaço dos outros. Esse número sozinho é como os itens dividem entre si o espaço restante.

Por trás de flex: 1 existem três controles separados: quanto um item cresce, quanto ele encolhe e seu tamanho inicial. No começo você raramente os define um por um, o atalho cobre os casos comuns, mas ajuda saber que eles existem.

Três propriedades decidem como os itens dividem o espaço. flex-grow define o quanto um item cresce para preencher o espaço restante (0 significa não crescer). flex-shrink define o quanto ele cede quando o espaço fica apertado (1, o padrão, significa que ele pode encolher). flex-basis define o tamanho inicial do item antes de crescer ou encolher, e o padrão é auto, ou seja, "use o conteúdo ou a largura".

O atalho flex reúne os três, e os valores que você realmente vai digitar são poucos:

css
.card {
  flex: 1;   /* grow 1, shrink 1, basis 0: colunas de largura igual */
}

.sidebar {
  flex: 0 0 240px;   /* não cresce, não encolhe, fica com 240px */
}

flex: 1 é o cavalo de batalha: faz os itens dividirem a linha em partes iguais, independentemente do conteúdo, porque o basis 0 faz eles começarem do zero e crescer só de acordo com o fator de crescimento. flex: 0 0 240px é a sidebar de largura fixa ao lado de uma área principal com flex: 1, um layout que você vai construir o tempo todo.

O dimensionamento dos itens é resolvido por três propriedades que o container avalia em ordem. flex-basis é o tamanho inicial do item no eixo principal, considerado antes de qualquer espaço livre ser distribuído; o padrão auto recorre ao width do item (ou ao tamanho do conteúdo). Depois, o container mede a diferença entre a soma dos valores de basis e o próprio tamanho. Se houver espaço livre, ele é distribuído proporcionalmente ao flex-grow de cada item. Se houver falta de espaço, ele é retirado proporcionalmente ao flex-shrink de cada item, ponderado pelo seu basis.

css
/* flex: 1 expande para flex-grow: 1, flex-shrink: 1, flex-basis: 0% */
.card {
  flex: 1;   /* basis 0, então os itens ignoram a largura do conteúdo e dividem o espaço pelo fator de crescimento */
}

O ponto sutil é flex-basis versus width, porque eles interagem. flex-basis: 0 (como em flex: 1) faz os itens ignorarem o conteúdo e dividir o espaço só pelo fator de crescimento, gerando colunas verdadeiramente iguais. flex-basis: auto (como em flex: auto, ou um width simples) faz cada item começar pelo tamanho do seu conteúdo ou pela largura declarada e só depois dividir o restante, então itens com mais conteúdo terminam mais largos. Escolher entre os dois é, na prática, escolher se o conteúdo deve influenciar as larguras finais.

Duas observações práticas. Primeiro, flex-basis vence width quando os dois estão definidos, então, uma vez que um item é um flex item, prefira expressar seu tamanho através de flex. Segundo, a pegadinha do overflow: um flex item tem por padrão min-width: auto, o que significa que ele se recusa a encolher além do tamanho intrínseco do seu conteúdo, então uma palavra longa ou um filho que extrapola pode arrebentar a linha inteira. A solução é min-width: 0 no item que deve poder encolher.

css
.main {
  flex: 1;
  min-width: 0;   /* permite que esse item encolha além do seu conteúdo, então um texto longo é truncado em vez de extrapolar */
}

align-self sobrescreve align-items para um único item, então um item pode ficar em flex-start enquanto o resto fica centralizado. E a decisão de ferramenta: recorra ao flexbox para layouts unidimensionais, uma barra de navegação, uma barra de ferramentas, uma única linha ou coluna de itens. Quando você precisa de linhas e colunas alinhadas ao mesmo tempo, o CSS grid é a ferramenta certa. Se você não tiver certeza de como as larguras se resolvem por trás disso tudo, unidades de dimensionamento explica como porcentagens e outras unidades se comportam aqui.

css
.layout {
  display: flex;
  gap: 24px;
}
.sidebar {
  flex: 0 0 240px;   /* fixo em 240px, nunca cresce ou encolhe */
}
.main {
  flex: 1;           /* ocupa todo o espaço restante */
}

Uma sidebar fixa ao lado de uma coluna principal flexível, três linhas que expressam a intenção. Esse padrão, junto com a barra de navegação alinhada de antes, cobre boa parte dos layouts que você vai construir.

JunoDimensionamento flexível dos itensflex: 1 em um item diz a ele para crescer e ocupar uma fração igual da linha, então três cards com flex: 1 saem com a mesma largura. Aumente um para flex: 2 e ele ocupa o dobro do espaço. Esse número sozinho é como os flex items dividem entre si o espaço disponível.
JunoDimensionamento flexível dos itens O atalho flex reúne grow, shrink e basis. flex: 1 gera colunas de largura igual porque seu basis 0 faz os itens começarem do zero e crescer de forma uniforme. flex: 0 0 240px é a sua sidebar fixa ao lado de uma área principal com flex: 1, um layout ao qual você vai recorrer repetidamente.
JunoDimensionamento flexível dos itensflex-basis é o tamanho inicial antes do espaço ser dividido, e ele vence width em um flex item, então flex: 1 (basis 0) divide o espaço igualmente enquanto flex: auto deixa o conteúdo influenciar as larguras. Preste atenção no padrão min-width: auto, que impede um item de encolher além do seu conteúdo e faz ele extrapolar a linha até você definir min-width: 0. Use align-self para tirar um item do alinhamento geral, e mude para grid no momento em que precisar de linhas e colunas alinhadas.