Aguarde...

12 de maio de 2019

Quebrando para uma nova linha com flexbox

Quebrando para uma nova linha com flexbox

qui está o desafio: se você quiser criar um layout flexbox com várias linhas de itens, como você controla qual item termina em qual linha? Suponha que você queira criar um layout parecido com este, com três itens empilhados e itens alternados de largura total:

Uma maneira comum de controlar o posicionamento e o tamanho dos itens flexíveis é usar widthou flex-basis; se definirmos o quarto item para ter uma largura de 100%, ele será posicionado em sua própria linha. Mas e se não quisermos ou não pudermos definir a largura de itens individuais, precisamos mesmo? Ou existe uma maneira de apenas dizer flexbox para quebra de linha em certos pontos?

Não há nenhuma propriedade que possamos definir em um item flexível para torná-lo uma nova linha, mas podemos inserir uma linha contraída (você pode pensar nisso como a <br>) entre dois itens flexíveis e dois conseguir algo semelhante. Em uma essência:

/* Inserting this collapsed row between two flex items will make 
 * the flex item that comes after it break to a new row */
.break {
  flex-basis: 100%;
  height: 0;
}
<div class="container">
  <div class="item"></div>
  <div class="break"></div> <!-- break -->
  <div class="item"></div>
</div>

Vamos percorrer alguns cenários em que você pode querer usar isso e observar algumas técnicas de layout interessantes que ele nos permite usar.

Note-se que todos os exemplos de código a seguir exige e pressupõe que você tenha um recipiente flexível com display: flexflex-wrap: wrape que os itens flexíveis são adicionados a esse recipiente:

.container {
  display: flex;
  flex-wrap: wrap;
}
<div class="container">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  ...
</div>

Inserindo um item flex de quebra de linha

Usar um elemento para quebrar uma nova linha flexível vem com um efeito interessante: podemos pular especificando a largura de qualquer item em nosso layout flexível e confiar completamente nas quebras de linha para definir o fluxo de nossa grade.

Vamos começar com um exemplo simples. Digamos que temos dois itens mostrados lado a lado (eles estão definidos para crescer flex-grow: 1e não têm definidos widthou flex-basis):

Podemos inserir um elemento de quebra de linha entre os itens para que ambos ocupem 100% do espaço disponível:

<div class="item">...</div>
<div class="break"></div> <!-- break to a new row -->
<div class="item">...</div>

Isso produz um layout com dois itens de largura total empilhados verticalmente (adicionei uma borda ao .breakelemento para ilustrar sua posição e comportamento):

Como é que isso funciona? Já que dissemos que .breakdeve ocupar 100% da largura do container (porque definimos flex-basis: 100%), o item flexível de quebra precisa ficar na sua própria linha para conseguir isso. Não é possível compartilhar uma linha com o primeiro item para que ele seja quebrado em uma nova linha, o que deixará o primeiro item sozinho em uma linha. O primeiro item irá então crescer para preencher o espaço restante (desde que definimos flex-grow: 1). A mesma lógica se aplica ao segundo item.

Podemos usar essa técnica para compor o layout na parte superior do post, quebrando antes e depois de cada quarto item:

<div class="item">...</div>
<div class="item">...</div>
<div class="item">...</div>
<div class="break"></div> <!-- break -->
<div class="item">...</div>
<div class="break"></div> <!-- break -->
<div class="item">...</div>
<div class="item">...</div>
<div class="item">...</div>

Isso produzirá o layout no topo da postagem do blog. Essencialmente, um item não será quebrado em uma nova linha, a menos que insira o elemento de quebra de linha:

Novamente, não precisamos especificar a largura em nenhum desses itens. A mesma técnica funcionará para colunas se tivermos um contêiner flexível flex-direction: columne definiremos width(em vez de height0para nosso elemento de quebra:

/* Use a collapsed column to break to a new column */
.break-column {
  flex-basis: 100%;
  width: 0;
}

Essa abordagem de usar elementos de quebra de linha para definir um layout definitivamente adiciona algum inchaço e ruído ao nosso HTML, mas pode ser uma ferramenta poderosa quando usada da maneira correta. Podemos, por exemplo, usá-lo para construir um layout de alvenaria apenas com CSS e posicionar as quebras de forma dinâmica com a orderpropriedade. Também podemos quebrar para uma nova linha sem ter que modificar a largura de qualquer item de conteúdo, e podemos confiar unicamente na flex-growdistribuição de espaço em um layout de grade.

Suponha que estamos procurando criar este layout:

E suponha que queremos fazer isso definindo valores diferentes flex-growpara distribuir o espaço (em vez de usar flex-basisou width, o que você teria que recalcular assim que você adicionasse ou removesse itens):

.item { flex-grow: 1; }
.item-wide { flex-grow: 3; }
<div class="item"></div>
<div class="item-wide"></div>
<div class="item"></div>

Se, em seguida, quisermos adicionar outra linha de itens abaixo dessa linha:

Não poderíamos fazê-lo sem recorrer à configuração flex-basisou widthem pelo menos alguns dos itens (ou criar um layout flexbox aninhado com um item flexível para cada linha). Se todos os itens tivessem valores diferentes de flex-grownada, eles iriam se dividir em uma nova linha, todos eles se juntariam em uma linha:

Aconchegante, mas não o que estamos procurando. Se inserirmos um elemento de quebra, no entanto, podemos construir esse layout distribuindo todo o espaço com flex-grow:

.item { flex-grow: 1; }
.item-wide { flex-grow: 3; }
<div class="item"></div>
<div class="item-wide"></div>
<div class="item"></div>
<div class="break"></div> <!-- break -->
<div class="item"></div>
<div class="item"></div>

Produzindo o layout desejado, com todos os tamanhos definidos proporcionalmente por flex-grow:

E se houver um cenário em que precisamos de cinco itens na primeira linha, não precisamos alterar nenhum CSS para que isso funcione, podemos adicionar esses itens antes da quebra de linha:

<div class="item"></div>
<div class="item"></div>
<div class="item-wide"></div>
<div class="item"></div>
<div class="item"></div>
<div class="break"></div> <!-- break -->
<div class="item"></div>
<div class="item"></div>

Tudo o que você precisa adicionar ao seu CSS para usar os elementos de quebra de linha são essas duas classes (a única diferença entre as duas classes é que width(e não height) precisa ser definida para 0que o elemento seja recolhido quando usado em um layout de coluna) :

/* Inserting a collapsed row between two flex items will make 
 * the flex item that comes after it break to a new row */
.break {
  flex-basis: 100%;
  height: 0;
}

/* Use a collapsed column to break to a new column */
.break-column {
  flex-basis: 100%;
  width: 0;
}

Você poderia certamente conseguir o mesmo efeito ou efeitos semelhantes aninhando flexboxes e ter um item flexível para cada linha, e em muitos casos apenas utilizando flex-basiswidthou o conteúdo dentro dos itens Flex é provavelmente a maneira preferida de controlar o fluxo de itens em um layout de flexbox. Mas a inserção de itens flexíveis de quebra de linha é acessível e fácil de criar, funciona e a técnica vem com algumas características únicas que podem ser úteis.

Postado em BlogTags:
Escreva um comentário