Caixa flexível: alinhar a última linha à grade


379

Eu tenho um layout simples de caixa flexível com um contêiner como:

.grid {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

Agora, quero que os itens na última linha estejam alinhados com os outros. justify-content: space-between;deve ser usado porque a largura e a altura da grade podem ser ajustadas.

Atualmente parece

O item no canto inferior direito deve estar no meio

Aqui, quero que o item no canto inferior direito esteja na "coluna do meio". Qual é a maneira mais simples de conseguir isso? Aqui está um pequeno jsfiddle que mostra esse comportamento.

.exposegrid {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

.exposetab {
  width: 100px;
  height: 66px;
  background-color: rgba(255, 255, 255, 0.2);
  border: 1px solid rgba(0, 0, 0, 0.4);
  border-radius: 5px;
  box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
  margin-bottom: 10px;
}
<div class="exposegrid">
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
</div>



Verifique minha solução aqui eu acho que funciona agradável, sem corte, apenas matemática: stackoverflow.com/questions/18744164/...
— Sebastien Lorber

5
Alternativamente, o uso poderia usar o mais recente módulo grade css - que não tem esse problema
— DanielD


11
Eu adicionei uma solução JS genérica para casos em que a largura do filho é variável, tornando o número de itens na linha variável também.
— tao

Respostas:


417

Adicione um ::afterque preencha automaticamente o espaço. Não há necessidade de poluir seu HTML. Aqui está um codepen mostrando: http://codepen.io/DanAndreasson/pen/ZQXLXj

.grid {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

.grid::after {
  content: "";
  flex: auto;
}

17
Seria possível fazê-lo funcionar de alguma maneira com o espaço?
— Tom

61
@DanAndreasson Há dois problemas: ele não inicia da esquerda (como espaço intermediário) e também o espaço entre os itens da última linha é diferente do da linha anterior (simulando alguns itens de largura fixa em "qualquer tamanho" grid - refere-se a ambos) ... codepen.io/anon/pen/gPoYZE O que eu queria era manter a "estratégia" (espaço ao redor ou espaço no meio), mas começar da esquerda como nas linhas anteriores ... I queria saber se é possível generalizar sua solução incrível.
— Tom

44
Isso só funciona porque os itens têm estofo para o espaço deles e as larguras percentuais combinados igual a 100% para cada conjunto de 4. Neste codepen I removido justify-content: space-between;a partir .gride removido .grid:aftere ele funciona da mesma. Agora, se você tentou algo assim, ele quebra totalmente. Observe que as larguras para cada conjunto de 4 não somam 100%. No violino do OP, as larguras são definidas em px, para que sua solução não funcione nessa situação.
— Jacob Alvarez

22
Tentando esta solução, inicialmente, os itens com que estava curto na última linha não foram distribuídos corretamente space-between. No entanto, quando eu definir a flex-basisde .grid:afterque o mesmo dimensionamento como os outros itens na grade (por ponto de interrupção, substituindo o código do módulo padrão / base acima), a última linha propagação corretamente. Parece funcionar no Safari, iOS, Firefox, Chrome (preciso testar o IE) e meu maior tamanho de linha é 3 na minha implementação inicial.
— Webbower

8
Para minhas necessidades, isso funcionou com a seguinte modificação: { content: "";flex: 0 0 32%;max-width: 480px;}e alterei a largura máxima com as alterações de consulta de mídia para que a grade fosse perfeita em todas as larguras.
— Colin Wiseman

160

Uma técnica seria inserir um número de elementos extras (o número máximo de elementos que você espera ter em uma linha) que recebem altura zero. O espaço ainda está dividido, mas as linhas supérfluas entram em colapso:

http://codepen.io/dalgard/pen/Dbnus

body {
  padding: 5%;
}

div {
  overflow: hidden;
  background-color: yellow;
}

ul {
  display: flex;
  flex-wrap: wrap;
  margin: 0 -4px -4px 0;
  list-style: none;
  padding: 0;
}

li {
  flex: 1 0 200px;
  height: 200px;
  border-right: 4px solid black;
  border-bottom: 4px solid black;
  background-color: deeppink;
}
li:empty {
  height: 0;
  border: none;
}

*,
:before,
:after {
  box-sizing: border-box;
}
<div>
  <ul>
    <li>a</li>
    <li>b</li>
    <li>c</li>
    <li>d</li>
    <li>e</li>
    <li>f</li>
    <li>g</li>
    <li>h</li>
    <li>i</li>
    <li>j</li>
    <li>k</li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
  </ul>
</div>

No futuro, isso pode ser possível através do uso de múltiplos ::after(n).


11
Infelizmente, isso contamina a marcação de maneira não-semântica, mas funciona totalmente. : SI gostaria de saber de outra maneira de replicar esse comportamento, flexbox ou não, que não exigisse os elementos não-semânticos.
— Ryan Norbauer

33
Concordou que está sujo, mas funciona e é menos invasivo do que muitos hacks. Estou usando, até :: after (12) obter suporte, ou eles adicionam algumas opções justificativas adicionais. É uma pena, pois a maneira como o flexbox justify funciona no momento está totalmente errado! Se você estivesse justificando um parágrafo do texto, nunca tentaria justificar a última linha. Definitivamente deveria ter sido uma opção, não acredito que eles tenham perdido isso.
— Codemonkey

4
Eu vim com uma solução apenas de CSS. A ressalva é que ela só pode ser responsável por dois itens ausentes, portanto, só funcionará com segurança em uma grade flexível com no máximo três itens por linha de quebra automática. Demo: codepen.io/lukejacksonn/pen/dozqVq O princípio aqui é usar pseudo-elementos como filhos extras e dar a eles a mesma propriedade flex que os itens no contêiner.
— lukejacksonn

8
@Codemonkey Jesus. Eu apenas comecei a usar o flexbox pensando em como me livrar de todos esses hacks destinados a alinhar os blocos em linha dentro de uma grade e agora acontece que isso simplesmente não é possível! Eu atingi esse bloco imediatamente, atingindo os limites que eu pensava que dificilmente chegaria a resolver alegremente todos esses velhos problemas insolúveis de CSS. Não é tão rápido, eu acho. Foram necessários apenas 20 anos para obter uma centralização vertical adequada - certamente podemos esperar. Jesus, parece uma tarefa tão simples ...
— Andrey

3
@dalgard Acho que não. Veja meu comentário .
— Jacob Alvarez

109

Como outros pôsteres mencionaram - não há uma maneira limpa de alinhar à esquerda a última linha com o flexbox (pelo menos conforme as especificações atuais)

No entanto, para o que vale a pena: Com o CSS Grid Layout Module, é surpreendentemente fácil de produzir:

Basicamente, o código relevante se resume a isso:

ul {
  display: grid; /* 1 */
  grid-template-columns: repeat(auto-fill, 100px); /* 2 */
  grid-gap: 1rem; /* 3 */
  justify-content: space-between; /* 4 */
}

1) Faça do elemento container um container grid

2) Defina a grade com colunas automáticas de largura 100px. (Observe o uso do preenchimento automático (ao contrário de auto-fit- que (para um layout de 1 linha) reduz as faixas vazias para 0 - fazendo com que os itens se expandam ocupem o espaço restante. Isso resultaria em um justificado espaço entre 'layout quando a grade tem apenas uma linha que, no nosso caso, não é o que queremos. (confira esta demonstração para ver a diferença entre elas).

3) Defina espaços / calhas para as linhas e colunas da grade - aqui, como deseja um layout de 'espaço entre' - o espaço será realmente um espaço mínimo, pois aumentará conforme necessário.

4) Semelhante ao flexbox.

Codepen Demo (Redimensione para ver o efeito)


4
Ótima solução. O único problema é que ele não funciona com o IE10 / 11.
— Zendu 28/10/19

11
Em relação a auto-fit, houve um bug no Chrome 57-60 (e navegadores baseados em seu mecanismo, como o Samsung Internet 6.0) porque a especificação era um pouco ambígua na época. Agora, as especificações foram esclarecidas e as novas versões do Chrome renderizadas auto-fitcorretamente, mas os navegadores com mecanismo antigo ainda estão em uso, portanto, tenha cuidado com esse valor.
— Ilya Streltsyn

4
À luz das possibilidades atuais, essa deve agora ser a resposta aceita. O uso de :afterpseudo-elemento pode levar a resultados indesejados em casos extremos.
— Paul

2
@ Danield essa sugestão me ajudou muito, obrigado!
— Krys

4
Essa deve ser a resposta aceita. Eu o combinaria com o flexbox como substituto, no espírito de aprimoramento progressivo: navegadores que não suportam a grade exibiriam a versão do flexbox, que é suficientemente próxima para mim.
— Palantir

27

Sem nenhuma marcação extra, apenas adicionar ::afterfuncionou para mim especificando a largura da coluna.

.grid {
  display:flex;
  justify-content:space-between;
  flex-wrap:wrap;
}
.grid::after{
  content: '';
  width: 10em // Same width of .grid__element
}
.grid__element{
  width:10em;
}

Com o HTML assim:

<div class=grid">
   <div class="grid__element"></div>
   <div class="grid__element"></div>
   <div class="grid__element"></div>
</div>

9
isso é interessante, mas não totalmente correto. o problema surge quando você lida com mais de dois elementos na linha inferior - o espaçamento que surge entre os elementos nas linhas acima nunca surge na última; os itens são compactados juntos, negando a utilidade original do espaço intermediário.
— John Haugeland

ainda melhor se você usar em flex-basis: 10emvez de largura.
— beytarovski 22/10/19

14

Você não pode. O Flexbox não é um sistema de grade. Ele não possui construções de linguagem para fazer o que você está pedindo, pelo menos não se você estiver usando justify-content: space-between. O mais próximo que você pode chegar do Flexbox é usar a orientação da coluna, que requer a definição de uma altura explícita:

http://cssdeck.com/labs/pvsn6t4z (observação: prefixos não incluídos)

ul {
  display: flex;
  flex-flow: column wrap;
  align-content: space-between;
  height: 4em;
}

No entanto, seria mais simples usar apenas colunas, que oferecem melhor suporte e não exigem a definição de uma altura específica:

http://cssdeck.com/labs/dwq3x6vr (observação: prefixos não incluídos)

ul {
  columns: 15em;
}

2
Há uma maneira; veja minha resposta.
— 21814 dalgard

@dalgard, sua resposta é uma solução alternativa, não uma solução verdadeira. a resposta de cimmanon está correta.
— Jonah

11
@ Jonah Eu acho que "técnica" é uma descrição justa da minha resposta. Certamente funcionou como uma solução para muitas pessoas, incluindo o solicitante.
— Dalgard

2
@dalgard Isso não muda o fato de o Flexbox não fornecer as construções de linguagem para fazer o que está sendo solicitado. Além disso, eu argumentaria que adicionar elementos falsos é uma prática extremamente suja, lá em cima com o uso de tabelas para layout.
— Cimmanon

4
Não é bonito, mas o desenvolvimento de front-end é a arte do possível; O pragmatismo é uma premissa básica. Acho que a palavra extremamente é equivocada, uma vez que elementos extras estão sendo usados para denominar em 99,9% dos sites do mundo real (elementos cf. Bootstrap contentor).
— Dalgard

12

Uma solução possível é usar justify-content: flex-start;no .gridcontêiner, restrições de tamanho em seus filhos e margens nas devidas elementos filhos - dependendo do número desejado de colunas.

Para uma grade de 3 colunas, o CSS básico seria assim:

.grid {
    display: flex;
    flex-flow: row wrap;
    justify-content: flex-start;
}

.grid > * {
    flex: 0 0 32%;
    margin: 1% 0;
}

.grid > :nth-child(3n-1) {
    margin-left: 2%;
    margin-right: 2%;
}

É outra solução imperfeita, mas funciona.

http://codepen.io/tuxsudo/pen/VYERQJ


11

Eu sei que há muitas respostas aqui, mas ... A maneira mais simples de fazer isso é com um em gridvez de flexe grid template columnscom repeate auto fills, onde você deve definir o número de pixels que você atribuiu a cada elemento, a 100pxpartir do seu código de trecho.

.exposegrid {
     display: grid;
     grid-template-columns: repeat(auto-fill, 100px);
     justify-content: space-between;
}
 .exposetab {
     width: 100px;
     height: 66px;
     background-color: rgba(255, 255, 255, 0.2);
     border: 1px solid rgba(0, 0, 0, 0.4);
     border-radius: 5px;
     box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
     margin-bottom: 10px;
}
<div class="exposegrid">
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
</div>


2
Esta é a solução adequada para alinhar os itens da última linha.
— precisa saber é o seguinte

Eu concordo, a maneira correta é usar a grade. Isso pode ser alcançado com o flexbox, mas muito mais limpo para usar a grade.
— Nbarth

6

Sim.! Podemos, mas com algumas consultas de mídia, o número máximo de colunas é predefinido .

Aqui estou usando 4 colunas. Verifique meu código:

.container {
  display: flex;
  display: -webkit-flex;
  display: -moz-flex;
  flex-flow: row wrap;
  -webkit-flex-flow: row wrap;
  -moz-flex-flow: row wrap;
}

.container .item {
  display: flex;
  display: -webkit-flex;
  display: -moz-flex;
  justify-content: center;
  -webkit-justify-content: center;
  -moz-justify-content: center;
  flex-basis: 25%; //max no of columns in %, 25% = 4 Columns
}

.container .item .item-child {
  width: 130px;
  height: 180px;
  background: red;
  margin: 10px;
}

@media (max-width: 360px) {
  .container .item {
    flex-basis: 100%;
  }
}

@media (min-width:360px) and (max-width: 520px) {
  .container .item {
    flex-basis: 50%;
  }
}

@media (min-width:520px) and (max-width: 680px) {
  .container .item {
    flex-basis: 33.33%;
  }
}
<div class="container">

  <div class="item">
    <div class="item-child">1</div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>

</div>

NOTA
1) Não há necessidade de criar div filho. Pode ser qualquer outra tag, como 'img' r, o que você quiser.
2) Se você quiser mais colunas, ajuste as consultas de mídia e o número máximo de colunas.


Isso cria apenas 3 no IE mais recente
— Akxe

6

Se você deseja uma grade com algum espaço entre os itens e os itens iniciados sem nenhum espaço inicial, esta solução simples funciona:

.grid {
    display: flex;
    flex-flow: row wrap;
    margin: 0 -5px; // remove the inital 5px space
    width: auto;
}
.grid__item {
    width: 25%;
    padding: 0 5px; // should be same as the negative margin above.
}

Se você deseja o espaço inicial de 5 px, remova a margem negativa :) Simples.

https://jsfiddle.net/b97ewrno/2/

A resposta aceita, embora boa, faz com que não haja espaço entre os elementos na segunda linha.


11
Surpreendeu que isso não tenha mais votos positivos. Essa é uma abordagem bonita que pertence ao museu Flex.
— Eduardo La Hoz Miranda 12/12

11
@EduardoLaHozMiranda thanks! Mas por que "museu"? O IE11 não suporta grade css e a maioria dos sites ainda precisa suportar isso. + Alguns temporizadores importantes no desenvolvimento de front-end ainda afirmam que existem casos de uso diferentes para grid vs flexbox. Mas talvez você só quisesse dizer que essa deveria ser uma parte importante do histórico da web: D
— OZZIE

11
Lol, sim. Eu estava empolgado na época. Só queria dizer que era uma ótima e mínima opinião sobre esse problema.
— Eduardo La Hoz Miranda

@dencey você não precisa saber que para esta solução, 25% de modo max 4 por linha, mas você pode usar qualquer cento que você quer
— OZZIE

@OZZIE Quero dizer que a largura do item é fixa (como 100px), mas a largura do contêiner é dinâmica, portanto os itens por linha são dinâmicos.
— dencey

4

Se você deseja alinhar o último item à grade, use o seguinte código:

Recipiente de grade

.card-grid {
  box-sizing: border-box;
  max-height: 100%;
  display: flex;
  flex-direction: row;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
  justify-content: space-between;
  align-items: stretch;
  align-content: stretch;
  -webkit-box-align: stretch;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
  -ms-flex-flow: row wrap;
  flex-flow: row wrap;
}

.card-grid:after {
  content: "";
  flex: 1 1 100%;
  max-width: 32%;
}

Item na grade

.card {
  flex: 1 1 100%;
  box-sizing: border-box;
  -webkit-box-flex: 1;
  max-width: 32%;
  display: block;
  position: relative;

}

O truque é definir a largura máxima do item igual à largura máxima da grade .card: after.

Demonstração ao vivo no Codepen


cthulu abençoa você e seu computador
— L422Y

3
Essa abordagem não funciona quando o tamanho do cartão é fixo e o número de cartões em cada linha é desconhecido. codepen.io/zendu/pen/WXNGvo
— zendu

3

É possível usar o "flex-start" e adicionar as margens manualmente. Requer alguns hackers matemáticos, mas é definitivamente fácil de fazer e facilita o uso com um pré-processador CSS como o LESS.

Veja, por exemplo, este mix MENOS:

.flexboxGridMixin(@columnNumber,@spacingPercent) {
  @contentPercent: 100% - @spacingPercent;
  @sideMargin: @spacingPercent/(@columnNumber*2);
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: flex-start;
  > * {
    box-sizing: border-box;
    width: @contentPercent/@columnNumber;
    margin-left: @sideMargin;
    margin-right: @sideMargin;
  }
}

E, em seguida, pode ser facilmente usado para exibir um layout de grade responsivo:

ul {
  list-style: none;
  padding: 0;
  @spacing: 10%;
  @media only screen and (max-width: 499px) { .flexboxGridMixin(1,@spacing); }
  @media only screen and (min-width: 500px) { .flexboxGridMixin(2,@spacing); }
  @media only screen and (min-width: 700px) { .flexboxGridMixin(3,@spacing); }
  @media only screen and (min-width: 900px) { .flexboxGridMixin(4,@spacing); }
  @media only screen and (min-width: 1100px) { .flexboxGridMixin(5,@spacing); }
}

li {
  background: pink;
  height: 100px;
  margin-top: 20px;
}

Aqui está um exemplo de

http://codepen.io/anon/pen/YyLqVB?editors=110


Você nunca usa @contentPercent. Você pretendeu?
— neverfox 31/01

width: @ contentPercent / @ columnNumber;
— Realtebo 3/07

UAU ! Estou realmente impressionado com esta solução. Vou tentar me adaptar à minha situação
— realtebo 3/17/17

3

Esse problema foi resolvido para mim usando a grade CSS,

Esta solução é aplicável apenas se você estiver tendo um número fixo de colunas, ou seja, não. de elementos a serem exibidos em uma única linha

-> usando grade, mas não especificando o número de linhas, à medida que o número de elementos aumenta, ele agrupa em colunas e adiciona linhas dinamicamente, especifiquei três colunas neste exemplo

-> você não precisa dar nenhuma posição ao seu (s) filho (s), pois ele o consertará, o que não queremos.

.grid-class{
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  column-gap: 80px;
}


1

Esta versão é a melhor maneira para blocos com largura fixa:

http://codepen.io/7iomka/pen/oxxeNE

Em outros casos - versão do dalgard

http://codepen.io/dalgard/pen/Dbnus

body {
  padding: 5%;
}

div {
  overflow: hidden;
  background-color: yellow;
}

ul {
  display: flex;
  flex-wrap: wrap;
justify-content:center;
  margin: 0 -4px -4px 0;
  list-style: none;
  padding: 0;
}

li {
  flex: 1 0 200px;
  height: 200px;
  max-width:200px;
  min-width:200px;
  border-right: 4px solid black;
  border-bottom: 4px solid black;
  background-color: deeppink;
}
li:empty {
  height: 0;
  border: none;
}

*,
:before,
:after {
  box-sizing: border-box;
}
<div>
  <ul>
    <li>a</li>
    <li>b</li>
    <li>c</li>
    <li>d</li>
    <li>e</li>
    <li>f</li>
    <li>g</li>
    <li>h</li>
    <li>i</li>
    <li>j</li>
    <li>k</li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
  </ul>
</div>


0

Existe uma maneira sem o flexbox, embora você precise atender às seguintes condições. 1) O recipiente possui preenchimento. 2) Os itens têm o mesmo tamanho e você sabe exatamente quantos deseja por linha.

ul {
  padding: 0 3% 0 5%;
}
li {
  display: inline-block; 
  padding: 0 2% 2% 0;
  width: 28.66%;
}

O preenchimento menor no lado direito do contêiner permite o preenchimento extra à direita de cada item da lista. Supondo que outros itens no mesmo pai que o objeto de lista sejam preenchidos com 0 a 5%, ele será alinhado com eles. Você também pode ajustar as porcentagens para a margem que desejar ou usar os valores de cálculo de px.

Obviamente, você pode fazer o mesmo sem o preenchimento no contêiner usando o enésimo filho (IE 9+) para remover a margem em cada terceira caixa.


0

Usando flexbox e algumas consultas de mídia, eu fiz essa pequena solução: http://codepen.io/una/pen/yNEGjv (é um pouco hacky, mas funciona):

.container {
  display: flex;
  flex-flow: row wrap;
  justify-content: flex-start;
  max-width: 1200px;
  margin: 0 auto;
}

.item {
  background-color: gray;
  height: 300px;
  flex: 0 30%;
  margin: 10px;

  @media (max-width: 700px) {
     flex: 0 45%;
  }

  @media (max-width: 420px) {
    flex: 0 100%;
  }

  &:nth-child(3n-1) {
    margin-left: 10px;
    margin-right: 10px;
  }
}

0

Eu fiz um SCSS mixin para ele.

@mixin last-row-flexbox($num-columns, $width-items){

  $filled-space: $width-items * $num-columns;
  $margin: calc((100% - #{$filled-space}) / (#{$num-columns} - 1));

  $num-cols-1 : $num-columns - 1;

  &:nth-child(#{$num-columns}n+1):nth-last-child(-n+#{$num-cols-1}) ~ & {
    margin-left: $margin;
  }
  @for $i from 1 through $num-columns - 2 { 
    $index: $num-columns - $i;
    &:nth-child(#{$num-columns}n+#{$index}):last-child{
      margin-right: auto;
    }
  }
}

Este é o link do codepen: http://codepen.io/diana_aceves/pen/KVGNZg

Você só precisa definir a largura dos itens em porcentagem e número de colunas.

Espero que isso possa ajudá-lo.


0

Aqui está outro par de scss mixins.

Esses mixins assumem que você não utilizará plug-ins js como o Isotope (eles não respeitam a ordem de marcação html, alterando assim as regras da css nth).

Além disso, você poderá tirar o máximo proveito deles, especialmente se estiver escrevendo seus pontos de interrupção responsivos da primeira maneira móvel. Idealmente, você usará flexbox_grid () no ponto de interrupção menor e flexbox_cell () nos seguintes pontos de interrupção. flexbox_cell () cuidará de redefinir as margens definidas anteriormente, que não serão mais usadas em pontos de interrupção maiores.

A propósito, desde que você configure corretamente as propriedades flex do seu contêiner, também poderá usar apenas flexbox_cell () nos itens, se necessário.

Aqui está o código:

// apply to the container (for ex. <UL> element)
@mixin flexbox_grid($columns, $gutter_width){

  display: flex;
  flex-direction:row;
  flex-wrap:wrap;
  justify-content: flex-start;

  > *{
    @include flexbox_cell($columns, $gutter_width);
  }
}

// apply to the cell (for ex. a <LI> element)
@mixin flexbox_cell($columns, $gutter_width){
  $base_width: 100 / $columns;
  $gutters: $columns - 1;
  $gutter_offset: $gutter_width * $gutters / $columns;

  flex-grow: 0;
  flex-shrink: 1;
  flex-basis: auto; // IE10 doesn't support calc() here

  box-sizing:border-box; // so you can freely apply borders/paddings to items
  width: calc( #{$base_width}% - #{$gutter_offset} );

  // remove useless margins (for cascading breakponts)
  &:nth-child(#{$columns}n){
    margin-right: 0;
  }

  // apply margin
  @for $i from 0 through ($gutters){
    @if($i != 0){
      &:nth-child(#{$columns}n+#{$i}){
        margin-right: $gutter_width;
      }
    }
  }
}

Uso:

ul{
   // just this:
   @include flexbox_grid(3,20px);
}

// and maybe in following breakpoints, 
// where the container is already setted up, 
// just change only the cells:

li{
   @include flexbox_cell(4,40px);
}

Obviamente, cabe a você definir eventualmente o preenchimento / margem / largura do contêiner e as margens inferiores da célula e similares.

Espero que ajude!


0

Isso é bastante hacky, mas funciona para mim. Eu estava tentando obter espaçamento / margens consistentes.

.grid {
  width: 1024px;
  display: flex;
  flex-flow: row wrap;
  padding: 32px;
  background-color: #ddd;  

  &:after {
    content: "";
    flex: auto;
    margin-left:-1%;
  }

  .item {
    flex: 1 0 24.25%;
    max-width: 24.25%;
    margin-bottom: 10px;
    text-align: center;
    background-color: #bbb;

    &:nth-child(4n+2),
    &:nth-child(4n+3),
    &:nth-child(4n+4) {
      margin-left: 1%;
    }

    &:nth-child(4n+1):nth-last-child(-n+4),
      &:nth-child(4n+1):nth-last-child(-n+4) ~ .item {
        margin-bottom: 0;
    }    

  }
}

http://codepen.io/rustydev/pen/f7c8920e0beb0ba9a904da7ebd9970ae/


0

Parece que ninguém propôs a solução flex-grow no último item. A idéia é ter seu último item flexível para ocupar todo o lugar possível usando o crescimento flexível: 1.

.grid {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

.grid > *:last-child {
  flex-grow: 1;
}

Nota: Essa solução não é perfeita, especialmente se você tiver elementos centralizados nos itens flexíveis, pois ele se concentrará no último item flexível possivelmente enorme.


0

Essa é uma combinação de muitas respostas, mas faz exatamente o que eu estava precisando - ou seja, alinhar o último filho em um contêiner flexível à esquerda, mantendo o comportamento entre espaços (neste caso, são três colunas layout).

Aqui está a marcação:

.flex-container {
  display: flex;
  justify-content: space-between;
  flex-direction: row;
}

.flex-container:after {
  content: "";
  flex-basis: 30%;
}

11
Para ser mais genérico: o tamanho da base flexível deve ser igual ao tamanho da criança.
— Christian Toffolo

11
Eu encontrei em flex-grow: 0.9vez de flex-basisobras para qualquer número de colunas. Testado em um monte de navegadores modernos - ele funciona em todos eles, mas o preenchimento é quebrado no IE (mas trabalhar em Edge0
— Patabugen

0

Assumindo:

  • Você deseja um layout de grade de 4 colunas com quebra automática
  • O número de itens não é necessariamente um múltiplo de 4

Defina uma margem esquerda em todos os itens, exceto nos itens 1, 5 e 9, e assim por diante. Se a margem esquerda for 10 px, cada linha terá uma margem de 30 px distribuída entre 4 itens. A largura percentual para o item é calculada da seguinte forma:

100% / 4 - horizontal-border - horizontal-padding - left-margin * (4 - 1) / 4

Esta é uma solução decente para problemas que envolvem a última linha do flexbox.

.flex {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  margin: 1em 0 3em;
  background-color: peachpuff;
}

.item {
  margin-left: 10px;
  border: 1px solid;
  padding: 10px;
  width: calc(100% / 4 - 2px - 20px - 10px * (4 - 1) / 4);
  background-color: papayawhip;
}

.item:nth-child(4n + 1) {
  margin-left: 0;
}

.item:nth-child(n + 5) {
  margin-top: 10px;
}
<div class="flex">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
</div>
<div class="flex">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
</div>
<div class="flex">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
  <div class="item">7</div>
  <div class="item">8</div>
  <div class="item">9</div>
</div>


0

Se você souber a largura dos espaços entre os elementos na linha e a quantidade de elementos em uma linha, isso funcionaria:

Exemplo: 3 elementos em uma linha, intervalo de 10 px entre elementos

div:last-child:nth-child(3n+2) {
  flex-grow: 1
  margin-left: 10px
}

0

Basta usar o truque Jquery / Javascript para adicionar uma div vazia:

if($('.exposegrid').length%3==2){
 $(".exposegrid").append('<div class="exposetab"></div>');
}

-1

Oh garoto, acho que encontrei uma boa solução com CSS mínimo e sem JS. Confira:

img {width:100%;}
li {
  display: inline-block;
  width:8em;
  list-style:none;
}
ul {text-align: justify;}
<ul>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>

A chave aqui é lembrar que o que estamos tentando alcançar é exatamente o que text-align: justifyfaz!

Os elementos vazios no HTML estão lá para fazer com que a última linha seja exibida perfeitamente sem alterar a aparência, mas pode não ser necessária, considerando o que você está tentando alcançar. Para um equilíbrio perfeito em todas as situações, você precisa de pelo menos x-4 elementos vazios, x sendo o número de elementos a serem exibidos ou n-2, n sendo o número de colunas que deseja exibir.


-1

Basta adicionar alguns itens falsos com as mesmas propriedades, exceto a altura definida como 0px até o final.


Adicionar itens falsos é uma prática ruim em todos os aspectos. Você não deve preencher o DOM com coisas apenas para invadir o CSS, a menos que seja obrigatório. Por muitas razões, desde a acessibilidade, até inundar a base de código com coisas estranhas, tornar a lógica mais complexa para entender e listar continua. Não recomende hacks, a menos que você diga explicitamente que pode ser uma solução ruim ou existe um caso especial para isso.
— Eksapsy

-4

você quer alinhar

use em align-content: flex-start;vez dejustify-content: space-between;

isso puxa os itens da última linha para a esquerda e também distribui o espaço uniformemente,

.container {
  display: flex;
  flex-flow: row wrap;
  align-content: flex-start;
  /*justify-content: space-between; remove this line!!!! */ 
}

https://codepen.io/anon/pen/aQggBW?editors=1100


A solução danAnderson NÃO É DINÂMICA.

quando a largura do item foi alterada de 25 para 28 dan anderson falha no espaço entre as imagens

danAnderson: https://codepen.io/anon/pen/ZwYPmB?editors=1100

dinâmico: https://codepen.io/anon/pen/aQggBW?editors=1100

isso é o que tenho tentado dizer. dans é hacky .....


-7

Consegui fazer isso justify-content: space-betweenno contêiner

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.