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.