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

Flexbox

docs.scrimba.com

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 contém. Nos velhos tempos isso significava floats, clearfixes e muito chute. Flexbox é a ferramenta construída exatamente para isso: você diz a um contêiner para organizar seus filhos em uma linha, e depois os empurra ao longo de dois eixos até ficarem onde você quer. A maioria dos layouts do dia a dia que você vê na web, barras de navegação, barras de ferramentas, linhas de cartões, tem um contêiner flex por baixo.

O contêiner flex

Flexbox começa com uma linha em um elemento pai. Defina display: flex em um contêiner e seus filhos diretos se alinham em uma linha, lado a lado. Esse contêiner é agora um contêiner flex, e cada filho dentro dele se torna um item flex.

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

Os itens se organizam ao longo de duas direções. O eixo principal vai da esquerda para a direita, a forma como os itens se alinham. O eixo transversal vai de cima para baixo, atravessando a linha. Você vai orientar itens ao longo de ambos, então ajuda visualizá-los agora: o eixo principal é a linha em que os itens ficam, o eixo transversal é a direção atravessando-a.

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

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

O modelo inteiro funciona em dois eixos. O eixo principal é a direção em que os itens fluem, uma linha por padrão, então da esquerda para a direita. O eixo transversal é perpendicular a ele, correndo de cima para baixo. Cada propriedade de alinhamento que você encontrar funciona em um eixo ou no outro, então manter os dois separados é o que torna o resto claro.

display: flex dá a um elemento um contexto de formatação flex: seus filhos diretos se tornam itens flex e são organizados pelo algoritmo flex em vez do fluxo normal. Apenas filhos diretos participam; execução de texto e descendentes aninhados são tratados abaixo deles. Esse é o mesmo tipo de limite que para o colapso de margem, que é uma razão pela qual layouts flex se comportam mais previsivelmente do que a era de float-and-clear que 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, então do início do inline até o final do inline), e o eixo transversal é perpendicular a ele. A distinção não é cosmética: justify-content sempre atua ao longo do eixo principal e align-items sempre atua 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. Nomear o layout por eixo em vez de "horizontal" e "vertical" é o que mantém coerência 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 começam a ficar em uma linha. Tudo mais neste capítulo é sobre orientar esses itens uma vez que estão no contêiner.

JunoO contêiner flex Coloque display: flex em um pai e seus filhos diretos se alinham em uma linha. Esse pai é o contêiner flex, os filhos são itens flex. Os itens se movem ao longo de duas direções: o eixo principal é a linha em que ficam, o eixo transversal corre atravessando-a, e você vai empurrar itens ao longo de ambos.
JunoO contêiner flexdisplay: flex faz um contêiner organizar seus filhos diretos como uma linha de itens flex. Apenas os filhos diretos participam, não qualquer coisa aninhada mais profundamente. Mantenha os dois eixos claros na sua cabeça: o eixo principal é a direção do fluxo, o eixo transversal é perpendicular, e cada propriedade de alinhamento funciona em um ou no outro.
JunoO contêiner flexdisplay: flex inicia um contexto de formatação flex, então filhos diretos se organizam pelo algoritmo flex e margens deixam de colapsar dentro dele. Nomeie o layout por eixo, não por horizontal e vertical, porque justify-content rastreia o eixo principal e align-items o eixo transversal. Mude flex-direction para column e esses dois trocam para qual lado empurram.

Alinhando ao longo dos eixos

Uma vez que seus itens estão em uma linha, duas propriedades os movem. justify-content espaça itens ao longo do eixo principal, a direção em que ficam. 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;   /* empurra itens para longe um do outro ao longo da linha */
  align-items: center;              /* alinha-os no meio vertical */
}

Os valores comuns para justify-content são flex-start (amontoados à esquerda), center (amontoados no meio), flex-end (amontoados à direita), space-between (espaços entre itens, nenhum nas extremidades), e space-around (espaços em ambos os lados de cada item). Para align-items, center é o que você alcança com mais frequência.

Para centralizar algo dos dois lados, o movimento que todos aprendem primeiro: defina ambos para 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 lidam com alinhamento, uma por eixo. justify-content distribui itens ao longo do eixo principal, e align-items os posiciona no eixo transversal. Porque possuem eixos diferentes, eles nunca se conflitam, apontam em direções perpendiculares.

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

Para justify-content, os valores que vale a pena saber são flex-start, center, flex-end, space-between (espaços iguais entre itens, alinhados com as extremidades), e space-around (espaço igual ao redor de cada item, então os espaços das extremidades são metade dos do meio). Para align-items, o padrão é stretch, que faz cada item preencher a altura do contêiner, e é por isso que uma linha de cartões sai com a mesma altura mesmo quando seu conteúdo difere. Defina align-items: center e eles encolhem de volta para a altura do conteúdo e ficam no meio.

Centralizar em ambos os eixos é o par de propriedades que torna 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 espaço livre ao longo do eixo principal, e align-items define a posição padrão do eixo transversal de cada item. Eles não podem conflitar porque operam em eixos perpendiculares, mas ambos dependem de qual direção é "principal", então uma flex-direction: column troca o que cada um controla.

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

A distinção que confunde as pessoas é que justify-content só tem algo a fazer quando há espaço sobrado no eixo principal. Ele distribui espaço livre, então se os itens já preenchem o contêiner (ou o transbordarem), space-between e center parecem idênticos porque não há nada a distribuir. align-items, por contraste, posiciona cada item independentemente dentro do tamanho do eixo transversal do contêiner, e seu valor inicial é stretch: itens sem tamanho fixo no eixo transversal crescem para preencher o contêiner. A linha de cartões de altura igual é align-items: stretch fazendo seu trabalho padrão. Anule-a por item com align-self, coberto na seção de dimensionamento abaixo.

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

Dois itens e um min-height no contêiner, ambos definidos para center, e você resolveu o problema de centralização que levou uma geração de desenvolvedores posicionamento absoluto e margens negativas para falsificar.

JunoAlinhando ao longo dos eixosjustify-content espaça 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 ambos para center e o que estiver dentro fica bem no meio, que é o movimento de layout que você vai usar uma e outra vez.
JunoAlinhando ao longo dos eixos Uma propriedade por eixo: justify-content no eixo principal, align-items no eixo transversal. O padrão align-items: stretch é por que uma linha de cartões sai com a mesma altura sem você pedir. E ambas definidas para center é o movimento de centralizar-qualquer-coisa que vale a pena memorizar.
JunoAlinhando ao longo dos eixosjustify-content distribui espaço sobrado no eixo principal, então se os itens já preenchem a linha ele não faz nada, o que explica muito dos momentos "por que isso não está centralizando". align-items posiciona cada item no eixo transversal e padrão para stretch, dando-lhe linhas de altura igual de graça. Mude flex-direction e lembre-se que ambas propriedades trocam para qual eixo atuam.

Direção e quebra

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

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

Quando itens em uma linha ficam sem espaço, eles ficam cada vez mais finos. Para deixá-los cair em uma nova linha, adicione flex-wrap: wrap.

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

Para o espaço entre itens, use gap. Ele adiciona um espaço consistente entre cada item sem adicionar espaço nas extremidades.

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

flex-direction define o eixo principal. O row padrão corre da esquerda para a direita; column transforma o eixo principal vertical, então itens se empilham de cima para baixo e, importante, justify-content agora controla espaçamento vertical enquanto align-items controla horizontal. Há também row-reverse e column-reverse se você precisa que a ordem seja invertida.

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: itens encolhem para caber em vez de quebrar. Defina flex-wrap: wrap e itens que não cabem se movem para uma nova linha, que é o que torna uma grade de cartões responsiva possível sem media queries.

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

Use gap para espaçamento, não margens nos itens. gap se aplica apenas entre itens, nunca nas extremidades, então você nunca tem que remover uma margem final do último filho.

flex-direction define o eixo principal, e cada propriedade dependente do eixo o segue. row (o padrão) torna o eixo principal horizontal; column torna vertical e silenciosamente reatribui justify-content para espaçamento vertical e align-items para horizontal. As variantes -reverse invertem a direção do eixo principal, mas note que apenas reordenam visualmente: a ordem do DOM não muda, então a ordem de teclado e leitor de tela ainda segue a fonte, que é uma consideração real de acessibilidade quando você alcanç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 ela, um contêiner flex força todos os itens em uma linha e distribui qualquer insuficiência encolhendo-os; com ela, itens que transbordam o tamanho principal quebram em novas linhas, e o contêiner se torna multi-linha. Uma vez que a quebra está ativada, align-content (distinta de align-items) governa como as linhas são espaçadas no eixo transversal. gap define o espaço entre itens e, quando quebrado, entre linhas, e é a ferramenta correta: diferente de margens não colapsam nada, adicionam sem espaço nas extremidades, e lê como uma única decisão de espaçamento.

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

Também é onde o limite com CSS grid aparece. Flex wrap preenche uma linha, depois quebra, então itens em linhas diferentes não se alinham em colunas. Quando você precisa de uma verdadeira grade bidimensional com linhas e colunas alinhadas, esse é o trabalho do grid, não do flexbox.

JunoDireção e quebraflex-direction: column empilha itens verticalmente em vez de em uma linha. flex-wrap: wrap deixa itens cair para uma nova linha quando ficam sem espaço, em vez de ficarem comprimidos. E gap coloca espaço mesmo entre itens sem adicionar nenhum nas extremidades, então recorra a ela antes de margens.
JunoDireção e quebraflex-direction define o eixo principal, e mudar para column significa que justify-content agora espaça verticalmente, que surpreende as pessoas uma vez. flex-wrap: wrap é o que torna uma linha de cartões reflua sem media queries. Use gap para espaçamento então você nunca persegue uma margem errante no último item.
JunoDireção e quebraflex-direction define o eixo principal e cada propriedade baseada em eixo o segue, enquanto os valores -reverse reordenam visualmente mas deixam a ordem do DOM e foco sozinhos, então use-os com cuidado. flex-wrap transforma um contêiner multi-linha e entrega espaçamento de linha para align-content. Quando itens quebrados precisam se alinhar em colunas reais, esse é grid, não flexbox.

Dimensionamento flexível de itens

O ponto do flexbox é que itens podem flexionar, crescendo ou encolhendo para compartilhar o espaço. O atalho que você vai usar mais é flex: 1 em um item, que diz a ele para crescer e pegar uma parte igual de qualquer espaço disponível.

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

Coloque flex: 1 em três cartões em uma linha e eles dividem o contêiner em três larguras iguais. Dê a um cartão flex: 2 e ele toma o dobro do espaço dos outros. Esse número único é como itens dividem o espaço sobrado entre eles.

Por trás de flex: 1 estão três controles separados: quanto um item cresce, quanto encolhe e seu tamanho inicial. Você raramente os define um por um no começo, o atalho cobre os casos comuns, mas ajuda saber que estão lá.

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

O atalho flex agrupa todos os três, e os valores que você realmente digita 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 240px */
}

flex: 1 é a ferramenta de trabalho: faz itens dividirem a linha em partes iguais independente do conteúdo, porque a base 0 significa que começam do nada e crescem apenas por seu fator de crescimento. flex: 0 0 240px é a barra lateral de largura fixa próxima a uma área principal flex: 1, um layout que você vai construir constantemente.

O dimensionamento de item se resolve por três propriedades que o contêiner avalia em ordem. flex-basis é o tamanho inicial do item no eixo principal, levado antes de qualquer espaço livre ser distribuído; seu padrão auto adia para width do item (ou tamanho do conteúdo). Então o contêiner mede a diferença entre a soma dos valores de base e seu próprio tamanho. Se há espaço livre, é entregue em proporção ao flex-grow de cada item. Se há um déficit, é retirado em proporção ao flex-shrink de cada item ponderado por sua base.

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

A parte sutil é flex-basis versus width, porque interagem. flex-basis: 0 (como em flex: 1) faz itens ignorarem seu conteúdo e dividirem espaço apenas por fator de crescimento, dando verdadeiras colunas iguais. flex-basis: auto (como em flex: auto, ou uma width simples) faz cada item começar em seu conteúdo ou largura declarada e apenas então compartilhar o restante, então itens com mais conteúdo acabam mais largos. Escolher entre eles é realmente escolher se conteúdo deve influenciar as larguras finais.

Duas notas de produção. Primeiro, flex-basis vence width quando ambos estão definidos, então uma vez que um item é um item flex, prefira expressar seu tamanho através de flex. Segundo, a armadilha de overflow: um item flex tem min-width: auto padrão, significando que recusa encolher abaixo do tamanho intrínseco do seu conteúdo, então uma palavra longa ou filho transbordando pode explodir toda a linha. O conserto é min-width: 0 no item que deve ser permitido encolher.

css
.main {
  flex: 1;
  min-width: 0;   /* deixa esse item encolher abaixo do conteúdo, então texto longo é truncado em vez de transbordar */
}

align-self anula align-items para um único item, então um item pode ficar em flex-start enquanto o resto centraliza. E a dica de ferramentas: recorra a flexbox para layouts unidimensionais, uma barra de navegação, uma barra de ferramentas, uma linha ou coluna única de itens. Quando você precisa de linhas e colunas alinhadas ao mesmo tempo, CSS grid é a ferramenta certa. Se você não tem certeza como as larguras se resolvem sob tudo isso, unidades de dimensionamento cobre como percentuais e outras unidades se comportam aqui.

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

Uma barra lateral fixa ao lado de uma coluna principal flexível, três linhas de intenção. Esse padrão único, mais a barra de navegação alinhada de antes, cobre uma grande fatia dos layouts que você vai construir.

JunoDimensionamento flexível de itensflex: 1 em um item diz a ele para crescer e pegar uma parte igual da linha, então três cartões com flex: 1 saem com a mesma largura. Aumente um para flex: 2 e ele toma o dobro do espaço. Esse número único é como itens flex dividem o espaço entre eles.
JunoDimensionamento flexível de itens O atalho flex agrupa crescimento, encolhimento e base. flex: 1 dá colunas de largura igual porque sua base 0 faz itens começarem do nada e crescerem uniformemente. flex: 0 0 240px é sua barra lateral fixa ao lado de uma área principal flex: 1, um layout que você vai alcançar uma e outra vez.
JunoDimensionamento flexível de itensflex-basis é o tamanho inicial antes do espaço ser compartilhado, e vence width em um item flex, então flex: 1 (base 0) divide espaço uniformemente enquanto flex: auto deixa conteúdo influenciar larguras. Observe o min-width: auto padrão, que para um item de encolher abaixo do conteúdo e transborda a linha até você definir min-width: 0. Use align-self para retirar um item do alinhamento, e mude para grid no momento em que você precisa de linhas e colunas alinhadas.