Melhor maneira de definir a distância entre itens flexbox

781

Para definir a distância mínima entre itens flexbox que estou usando margin: 0 5pxno .iteme margin: 0 -5pxno recipiente. Para mim, parece um hack, mas não consigo encontrar uma maneira melhor de fazer isso.

Exemplo

#box {
  display: flex;
  width: 100px;
  margin: 0 -5px;
}
.item {
  background: gray;
  width: 50px;
  height: 50px;
  margin: 0 5px;
}
<div id='box'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

Sasha Koss
fonte
29
Não é um truque - é um dos métodos pretendidos para alinhar itens. Existem outras propriedades embora. Consulte w3.org/TR/css3-flexbox/#alignment
BoltClock
4
Sim, eu entendo. Mas, por exemplo, há propriedade column-gap que nos dá capacidade de distância de controle de recipiente: w3.org/TR/css3-multicol/#column-gap
Sasha Koss
Por uma causa, há uma margem recolhida do flexbox. A outra pergunta tem o problema mais alto de [Como posso parar a última margem recolhida no flexbox? ] ( stackoverflow.com/questions/38993170/… )
Jack Yang
6
O nível 3 do módulo de alinhamento de caixas CSS inclui uma seção sobre lacunas entre caixas - que se aplica a elementos de várias colunas, contêineres flexíveis e contêineres de grade. Então, eventualmente, isso será simples como: row-gap: 5px- feito.
Danield
2
@JohnCarrell O firefox atualmente já suporta a gappropriedade em contêineres flexíveis ( caniuse ) #
Danield

Respostas:

428
  • O Flexbox não possui margens em colapso.
  • O Flexbox não tem nada parecido com as border-spacingtabelas (exceto a propriedade CSS, gapque não é bem suportada na maioria dos navegadores, caniuse )

Portanto, conseguir o que você está pedindo é um pouco mais difícil.

Na minha experiência, a maneira "mais limpa" que não usa :first-child/ :last-childe funciona sem nenhuma modificação flex-wrap:wrapé colocar padding:5pxno contêiner e margin:5pxnas crianças. Isso criará uma 10pxlacuna entre cada criança e entre cada criança e seus pais.

Demo

.upper
{
  margin:30px;
  display:flex;
  flex-direction:row;
  width:300px;
  height:80px;
  border:1px red solid;

  padding:5px; /* this */
}

.upper > div
{
  flex:1 1 auto;
  border:1px red solid;
  text-align:center;

  margin:5px;  /* and that, will result in a 10px gap */
}

.upper.mc /* multicol test */
{flex-direction:column;flex-wrap:wrap;width:200px;height:200px;}
<div class="upper">
  <div>aaa<br/>aaa</div>
  <div>aaa</div>
  <div>aaa<br/>aaa</div>
  <div>aaa<br/>aaa<br/>aaa</div>
  <div>aaa</div>
  <div>aaa</div>
</div>

<div class="upper mc">
  <div>aaa<br/>aaa</div>
  <div>aaa</div>
  <div>aaa<br/>aaa</div>
  <div>aaa<br/>aaa<br/>aaa</div>
  <div>aaa</div>
  <div>aaa</div>
</div>

Todos os trabalhadores são essenciais
fonte
220
Isso não faz o mesmo que a pergunta: você terá um recuo de 10px na extrema esquerda e direita, o que eu suponho que eles não pretendam ter. Portanto, as margens negativas na pergunta original.
Chris Nicola
17
E se a orderpropriedade estiver definida? :first-child/:last-childnão funcionará como esperado.
Guria
4
"O Flexbox não tem margens em colapso." Muito perspicaz e aparentemente verdadeiro, mas posso pedir uma citação?
22416 chharvey
2
Não é uma resposta pior do que a pergunta original? Esse método exige que você tenha espaço ao redor do contêiner e a calha deve sempre ser um número par.
limitlessloop
7
@chharvey, da especificação w3.org/TR/css-flexbox-1/#item-margins , "As margens dos itens flexíveis adjacentes não diminuem ."
Romellem
197

Isso não é um hack. A mesma técnica também é usada pelo bootstrap e sua grade, embora, em vez de margem, o bootstrap use preenchimento para suas colunas.

.row {
  margin:0 -15px;
}
.col-xx-xx {
  padding:0 15px;
}
Roumelis George
fonte
1
O único problema desse método é manter itens de altura igual com cores de plano de fundo. O posicionamento absoluto com height:100%; width:100%ignora o preenchimento do item.
Steven Vachon
3
O problema aqui é com os flex-basisvalores do IE10 e 11. não são considerados box-sizing: border-box, portanto, um filho com qualquer preenchimento ou borda transbordará o pai (ou quebrará nesse caso). Fonte
Carson
18
Há outro problema com essa abordagem: ajustar a margem dessa maneira pode expandir a largura da página. Exemplo
Nathan Osman
4
Embora eu concorde que isso não seja um hack, o fato de que algo é amplamente usado não significa que não seja um hack. Veja polyfills, patches de segurança temporários, edição hexadecimal, etc, etc #
William
15
Claro que isso é um hack. Como o Bootstrap usa esse método , não significa que não seja um hack. Significa apenas que o Bootstrap usa um hack.
Michael Benjamin
108

Flexbox e css calc com suporte a várias linhas

Olá, abaixo está a minha solução de trabalho para todos os navegadores que suportam o flexbox. Sem margens negativas.

Fiddle Demo

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

.flexbox > div {
  /*
    1/3  - 3 columns per row
    10px - spacing between columns 
  */
  box-sizing: border-box;
  margin: 10px 10px 0 0;
  outline: 1px dotted red;
  width: calc(1/3*100% - (1 - 1/3)*10px);
}

/*
  align last row columns to the left
  3n - 3 columns per row
*/
.flexbox > div:nth-child(3n) {
  margin-right: 0;
}

.flexbox::after {
  content: '';
  flex: auto;
}

/*
  remove top margin from first row
  -n+3 - 3 columns per row 
*/
.flexbox > div:nth-child(-n+3) {
  margin-top: 0;
}
<div class="flexbox">
  <div>col</div>
  <div>col</div>
  <div>col</div>
  <div>col</div>
  <div>col</div>
</div>

Observe que esse código pode ser mais curto usando o SASS

Atualização 2020.II.11 Colunas alinhadas na última linha à esquerda

Atualização 2020.II.14 Removida a margem inferior na última linha

Dariusz Sikorski
fonte
13
Eu gosto dessa solução, mas ela falhará se houver apenas 2 itens na última linha. Os itens não são empilhados juntos devido ao justify-content.
James Brantly
4
para corrigir o problema de dois itens, mude para justify-content: space-evenly;ou justify-content: space-around;.
Paul Rooney
6
@PaulRooney No site com várias listas, você nem sempre sabe o número de itens, se as listas forem geradas por um CMS.
NinjaFart #
1
@ 1.21gigawatts Por favor, não faça alterações arbitrárias no código / resposta de outra pessoa; escreva sua própria resposta.
TylerH
2
@TylerH Não foi arbitrário. A pergunta foi feita como "... para definir a distância entre itens do flexbox". Esta resposta não mostra o tamanho da sarjeta. Definir uma cor de fundo mostra a sarjeta. A adição de uma borda mostra que há margem abaixo da última linha.
1.21 gigawatts
93

Você pode usar bordas transparentes.

Eu considerei esse problema enquanto tentava criar um modelo de grade flexível que pudesse retornar a um modelo de tabelas + células de tabela para navegadores mais antigos. E bordas para calhas de colunas me pareciam a melhor escolha apropriada. isto é, as células da tabela não têm margens.

por exemplo

.column{
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-bottom: 10px solid transparent;
}

Observe também que você precisa min-width: 50px;do flexbox. O modelo flexível não manipula tamanhos fixos, a menos que você faça flex: none;o elemento filho específico que deseja como fixo e, portanto, excluído de existir "flexi". http://jsfiddle.net/GLpUp/4/ Mas todas as colunas juntas flex:none;não são mais um modelo flexível. Aqui está algo mais próximo de um modelo flexível: http://jsfiddle.net/GLpUp/5/

Portanto, você pode usar as margens normalmente se não precisar do fallback de célula de tabela para navegadores mais antigos. http://jsfiddle.net/GLpUp/3/

A configuração background-clip: padding-box;será necessária ao usar um plano de fundo, caso contrário, o plano de fundo fluirá para a área de borda transparente.

hexalys
fonte
5
Ótima resposta. margens são utilizados de forma diferente no de flexbox (como para absorver o espaço extra), de modo fronteiras transparentes proporcionar uma excelente solução para os elementos espaçados uniformemente que pode enrolar com uma margem semelhante comportamento
Eolis
4
exceto quando você usa a cor de fundo, o fundo excede os limites desejados.
Ahnbizcad
2
@ahnbizcad Bem, com diferentes cores de plano de fundo, você pode usar o branco ou a cor adequada, dependendo de qual é o plano de fundo.
Hexalys 30/04/2015
27
@ahnbizcad: Se você não precisa de suporte IE8, esta é uma solução melhor:background-clip: padding-box
Albin
5
O comentário de Albin aqui precisa de mais votos! essa é a melhor solução. Bordas transparentes, em combinação com clipe de fundo: caixa de preenchimento (e margens negativas no contêiner, se necessário, para o alinhamento correto da borda) é uma solução perfeita. O IE8 não suporta flexbox de qualquer maneira, portanto, sua falta de suporte ao clipe de segundo plano não deve importar.
Brian
74

Esta solução funcionará para todos os casos, mesmo se houver várias linhas ou qualquer número de elementos. Mas a contagem da seção deve ser a mesma que você deseja 4 na primeira linha e 3 na segunda linha, não funcionará dessa maneira, o espaço para o quarto conteúdo ficará em branco e o contêiner não será preenchido.

Nós estamos usando display: grid; e suas propriedades.

#box {
  display: grid;
  width: 100px;
  grid-gap: 5px;
  /* Space between items */
  grid-template-columns: 1fr 1fr 1fr 1fr;
  /* Decide the number of columns and size */
}

.item {
  background: gray;
  width: 100%;
  /* width is not necessary only added this to understand that width works as 100% to the grid template allocated space **DEFAULT WIDTH WILL BE 100%** */
  height: 50px;
}
<div id='box'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

A desvantagem deste método está no Mobile Opera Mini não será suportado e no PC isso funciona apenas após o IE10 .

Nota para compatibilidade completa do navegador, incluindo o IE11, use o Autoprefixer


RESPOSTA ANTIGA

Não pense nisso como uma solução antiga, ainda é uma das melhores se você deseja apenas uma única linha de elementos e funcionará com todos os navegadores.

Esse método é usado pela combinação de irmãos CSS , para que você possa manipulá-lo de várias outras maneiras também, mas se sua combinação estiver errada, também poderá causar problemas.

.item+.item{
  margin-left: 5px;
}

O código abaixo fará o truque. Nesse método, não há necessidade de fornecer margin: 0 -5px;ao #boxwrapper.

Uma amostra de trabalho para você:

#box {
  display: flex;
  width: 100px;
}
.item {
  background: gray;
  width: 22px;
  height: 50px;
}
.item+.item{
 margin-left: 5px;
}
<div id='box'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

weBBer
fonte
Editei sua resposta baseada em grade para demonstrar que funciona corretamente, mesmo que a linha final tenha menos itens. Para provar que funciona nesse caso. (Sinta-se livre para reverter, se você não gosta dessa mudança.)
ToolmakerSteve
De acordo com essa pergunta, eles pediram apenas para preencher o espaço adequadamente com os elementos filhos sem hackear, que o que eu fiz, usando a grade, podemos gerenciar de acordo com o grid-template-columnsque definimos não dinamicamente. Portanto, se você atribuir o valor 1fr 1fr 1fr 1fr, ele dividirá a div 4fractionse tentará preencher os elementos filhos em cada uma fractions, pelo que sei, é a única maneira de entrar grid. O que afirmei na resposta é que, se o usuário precisar dividir a div em 4 e usá-los com muitos elementos, mesmo para várias linhas, gidisso ajudará.
weBBer 31/10/19
69

Você pode usar & > * + *como seletor para emular um flex-gap(para uma única linha):

#box { display: flex; width: 230px; outline: 1px solid blue; }
.item { background: gray; width: 50px; height: 100px; }

/* ----- Flexbox gap: ----- */

#box > * + * {
  margin-left: 10px;
}
<div id='box'>
    <div class='item'></div>
    <div class='item'></div>
    <div class='item'></div>
    <div class='item'></div>
</div>

Se você precisar suportar flex wrapping , poderá usar um elemento wrapper:

.flex { display: flex; flex-wrap: wrap;  }
.box { background: gray; height: 100px; min-width: 100px; flex: auto; }
.flex-wrapper {outline: 1px solid red; }

/* ----- Flex gap 10px: ----- */

.flex > * {
  margin: 5px;
}
.flex {
  margin: -5px;
}
.flex-wrapper {
  width: 400px; /* optional */
  overflow: hidden; /* optional */
}
<div class='flex-wrapper'>
  <div class='flex'>
    <div class='box'></div>
    <div class='box'></div>
    <div class='box'></div>
    <div class='box'></div>
    <div class='box'></div>
  </div>
</div>

Do Async
fonte
3
Solução limpa. Funciona para qualquer número de elementos filho flex.
Konrad Gałęzowski 21/01
1
Era isso que eu estava procurando e funcionou muito bem para mim 👍
Paul Odeon
Um ponto a ser observado é que o *operador não aumenta a especificidade como você poderia esperar. Portanto, dependendo do css existente, pode ser necessário aumentar a especificidade no .flex > *seletor ou adicionar !importantà regra se houver outros seletores aplicando margem a esse elemento.
Paul Odeon
Melhor solução 👍
o01
26

Digamos que se você deseja definir o 10pxespaço entre os itens, você pode definir .item {margin-right:10px;}todos e redefini-lo no último.item:last-child {margin-right:0;}

Você também pode usar o irmão geral ~ou o +seletor de irmão seguinte para definir a margem esquerda nos itens, excluindo o primeiro .item ~ .item {margin-left:10px;}ou usar.item:not(:last-child) {margin-right: 10px;}

O Flexbox é tão inteligente que recalcula automaticamente e distribui igualmente a grade.

body {
  margin: 0;
}

.container {
  display: flex;
}

.item {
  flex: 1;
  background: gray;
  height: 50px;
}

.item:not(:last-child) {
  margin-right: 10px;
}
<div class="container">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
</div>

Se você deseja permitir flex wrap , consulte o exemplo a seguir.

body {
  margin: 0;
}

.container {
  display: flex;
  flex-wrap: wrap;
  margin-left: -10px;
}

.item {
  flex: 0 0 calc(50% - 10px);
  background: gray;
  height: 50px;
  margin: 0 0 10px 10px;
}
<div class="container">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
</div>

Adesivos
fonte
6
Isso não funcionaria se os itens estivessem quebrados, pois :last-childnão afeta cada último filho no final de uma linha, correto?
Flimm
2
@ Flimm Adicionei uma abordagem para trabalhar com flex wrap, veja a segunda parte acima.
Stickers
Melhor resposta para mim ... simples, limpo, eficiente! Funcionou perfeitamente com filme flexível, obrigado
Matthieu Marcé
16

Eu encontrei uma solução baseada no seletor geral de irmãos ~, e permite o aninhamento infinito.

Veja esta caneta de código para um exemplo de trabalho

Basicamente, dentro dos contêineres da coluna, todo filho que é precedido por outro filho recebe uma margem superior. Da mesma forma, dentro de cada contêiner de linha, todo filho que é precedido por outro recebe uma margem esquerda.

.box {
  display: flex;
  flex-grow: 1;
  flex-shrink: 1;
}

.box.columns {
  flex-direction: row;
}

.box.columns>.box~.box {
  margin-left: 5px;
}

.box.rows {
  flex-direction: column;
}

.box.rows>.box~.box {
  margin-top: 5px;
}
<div class="box columns">
  <div class="box" style="background-color: red;"></div>
  <div class="box rows">
    <div class="box rows">
      <div class="box" style="background-color: blue;"></div>
      <div class="box" style="background-color: orange;"></div>
      <div class="box columns">
        <div class="box" style="background-color: yellow;"></div>
        <div class="box" style="background-color: pink;"></div>
      </div>
    </div>
    <div class="box" style="background-color: green;"></div>
  </div>
</div>

Simon Epskamp
fonte
Isso resulta em itens de tamanhos diferentes devido às margens não serem aplicadas globalmente.
Steven Vachon
Você também precisará adicionar um CSS extra para lidar com telas menores, pois parece um pouco estranho no celular. Eu aplicaria a regra .box ~ .box em telas maiores e, para telas menores, defina a classe .box para ter uma largura máxima. de 100% e um fundo de margem.
rhysclay
14

Passando da resposta de sawa, aqui está uma versão ligeiramente aprimorada que permite definir um espaçamento fixo entre os itens sem a margem circundante.

http://jsfiddle.net/chris00/s52wmgtq/49/

Também está incluída a versão "-webkit-flex" do Safari.

.outer1 {
    background-color: orange;
    padding: 10px;
}

.outer0 {
    background-color: green;
    overflow: hidden;
}

.container
{
    display: flex;
    display: -webkit-flex;
    flex-wrap: wrap;    
    -webkit-flex-wrap: wrap;
    background-color: rgba(0, 0, 255, 0.5);
    margin-left: -10px;
    margin-top: -10px;
}

.item
{
    flex-grow: 1;
    -webkit-flex-grow: 1;
    background-color: rgba(255, 0, 0, 0.5);
    width: 100px;
    padding: 10px;
    margin-left: 10px;
    margin-top: 10px;
    text-align: center;
    color: white;
}

<div class="outer1">
    <div class="outer0">
        <div class="container">
            <div class="item">text</div>
            <div class="item">text</div>
            <div class="item">text</div>
            <div class="item">text</div>
            <div class="item">text</div>
            <div class="item">text</div>
        </div>
    </div>
</div>
chris
fonte
2
Isso não é essencialmente o mesmo que o exemplo dado na pergunta?
Ford #
10

De acordo com o #ChromDevSummit, há uma implementação de gappropriedade para o Flexbox, embora no momento (14 de novembro de 2019) ele seja suportado apenas no Firefox, mas deva ser implementado no Chrome em breve:

insira a descrição da imagem aqui

Demonstração ao vivo

Também atualizarei minha resposta quando chegar ao Chrome.

Eliya Cohen
fonte
9

Eu usei isso para colunas de largura fixa e empacotada. A chave aqui écalc()

Amostra SCSS

$gap: 10px;

dl {
  display: flex;
  flex-wrap: wrap;
  padding: $gap/2;

  dt, dd {
    margin: $gap/2;}

  dt { // full width, acts as header
    flex: 0 0 calc(100% - #{$gap});}

  dd { // default grid: four columns 
    flex: 0 0 calc(25% - #{$gap});}

  .half { // hall width columns
    flex: 0 0 calc(50% - #{$gap});}

}

Exemplo completo de Codepen

Veiko Jääger
fonte
2
Isso ainda adiciona uma calha antes do primeiro e depois do último item, que o OP impede de usar margens negativas.
herman
2
Não Flexbox não suporta calc () dentro alínea "Flex" no IE 11.
Adam Šipický
Não pode ser sempre usado. imagine se há também fronteira necessário para criança diretos
Andris
9

Um contêiner flexível com margem -x (negativa) e itens flexíveis com margem x (positiva) ou preenchimento resultam no resultado visual desejado: Os itens flexíveis têm um intervalo fixo de 2x apenas entre si.

Parece ser simplesmente uma questão de preferência, seja para usar margem ou preenchimento nos itens flexíveis.

Neste exemplo, os itens flexíveis são dimensionados dinamicamente para preservar a diferença fixa:

.flex-container { 
  margin: 0 -5px;
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

.flex-item {
  margin: 0 5px; // Alternatively: padding: 0 5px;
  flex: 1 0 auto;
}
Tim
fonte
3
Desculpe, eu não entendi. Quais são as novidades introduzidas pela sua resposta que não estão diretamente relacionadas à pergunta?
usuário
Em primeiro lugar, eu queria resumir que margem e preenchimento no item flexível levam ao resultado desejado, porque as respostas existentes mencionam apenas uma ou outra. Em segundo lugar, eu queria dar um exemplo, em que as lacunas são preservadas escalando os próprios itens flexíveis.
Tim
Aqui está um exemplo de codepen mostrando esse efeito. codepen.io/dalgard/pen/Dbnus
pedalpete
8

Eventualmente, eles adicionarão a gappropriedade ao flexbox. Até então, você poderia usar a grade CSS, que já possui a gappropriedade, e apenas ter uma única linha. Melhor do que lidar com margens.

Ollie Williams
fonte
Discussão aqui: github.com/w3c/csswg-drafts/issues/1696 - eles também simplificarão a nomeação, nas CSS Grid, Flexbox e CSS Columns.
Frank Lämmer
6

gapPropriedade CSS :

Há uma nova gappropriedade CSS para layouts de múltiplas colunas, caixas flexíveis e grade que funciona em alguns navegadores agora! (Consulte Posso usar o link 1 ; link 2 ).

#box {
  display: flex;
  flex-wrap: wrap;
  width: 200px;
  background-color: red;
  gap: 10px;
}
.item {
  background: gray;
  width: 50px;
  height: 50px;
}
<div id='box'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

Até o momento, isso só funciona no Firefox infelizmente. Atualmente, ele funciona no Chrome se você ativar "Ativar recursos experimentais da plataforma web" emabout:flags .

Flimm
fonte
5

Usando o Flexbox em minha solução, usei a justify-contentpropriedade para o elemento pai (contêiner) e especifiquei as margens dentro da flex-basispropriedade dos itens. Verifique o snippet de código abaixo:

.container {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-around;
  margin-bottom: 10px;
}

.item {
  height: 50px;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #999;
}

.item-1-4 {
  flex-basis: calc(25% - 10px);
}

.item-1-3 {
  flex-basis: calc(33.33333% - 10px);
}

.item-1-2 {
  flex-basis: calc(50% - 10px);
}
<div class="container">
  <div class="item item-1-4">1</div>
  <div class="item item-1-4">2</div>
  <div class="item item-1-4">3</div>
  <div class="item item-1-4">4</div>
</div>
<div class="container">
  <div class="item item-1-3">1</div>
  <div class="item item-1-3">2</div>
  <div class="item item-1-3">3</div>
</div>
<div class="container">
  <div class="item item-1-2">1</div>
  <div class="item item-1-2">2</div>
</div>

iClusterDev
fonte
5

Com o flexbox, criar calhas é uma dor, especialmente quando o embrulho está envolvido.

Você precisa usar margens negativas ( como mostrado na pergunta ):

#box {
  display: flex;
  width: 100px;
  margin: 0 -5px;
}

... ou altere o HTML ( como mostrado em outra resposta ):

<div class='flex-wrapper'>
  <div class='flex'>
    <div class='box'></div>
    <div class='box'></div>
            ...
  </div>
</div>

... ou alguma outra coisa.

De qualquer forma, você precisa de um truque feio para fazê-lo funcionar, porque o flexbox não fornece " flex-gap" um recurso ( pelo menos por enquanto ).

A questão das sarjetas, no entanto, é simples e fácil com o CSS Grid Layout.

A especificação Grid fornece propriedades que criam espaço entre os itens da grade, ignorando o espaço entre os itens e o contêiner. Essas propriedades são:

  • grid-column-gap
  • grid-row-gap
  • grid-gap (a abreviação de ambas as propriedades acima)

Recentemente, a especificação foi atualizada para estar em conformidade com o Módulo de alinhamento de caixas CSS , que fornece um conjunto de propriedades de alinhamento para uso em todos os modelos de caixas. Portanto, as propriedades são agora:

  • column-gap
  • row-gap
  • gap (forma abreviada)

No entanto, nem todos os navegadores que suportam o Grid suportam as propriedades mais recentes, então usarei as versões originais na demonstração abaixo.

Além disso, se o espaçamento for necessário entre os itens e o contêiner, ele paddingfuncionará perfeitamente (consulte o terceiro exemplo na demonstração abaixo).

Das especificações:

10.1 Calhas: os row-gap, column-gape gap Propriedades

As propriedades row-gape column-gap(e sua gapabreviação), quando especificadas em um contêiner de grade, definem as calhas entre as linhas e as colunas da grade. Sua sintaxe é definida em Alinhamento de caixas CSS 3 §8 Lacunas entre caixas .

O efeito dessas propriedades é como se as linhas de grade afetadas adquirissem espessura: a trilha da grade entre duas linhas de grade é o espaço entre as sarjetas que as representam.

.box {
  display: inline-grid;
  grid-auto-rows: 50px;
  grid-template-columns: repeat(4, 50px);
  border: 1px solid black;
}

.one {
  grid-column-gap: 5px;
}

.two {
  grid-column-gap: 10px;
  grid-row-gap: 10px;
}

.three {
  grid-gap: 10px;
  padding: 10px;
}

.item {
  background: lightgray;
}
<div class='box one'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

<hr>

<div class='box two'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

<hr>

<div class='box three'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

Mais Informações:

Michael Benjamin
fonte
4

Por que não fazer assim:

.item + .item {
    margin-left: 5px;
}

Isso usa o seletor de irmão adjacente , para fornecer todos os .itemelementos, exceto o primeiro a margin-left. Graças ao flexbox, isso resulta em elementos igualmente amplos. Isso também pode ser feito com elementos posicionados verticalmente e margin-top, é claro.

ladrilhadores
fonte
8
Isso funcionaria desde que os itens flexíveis estejam sempre em uma única linha. Se a embalagem for permitida, provavelmente não será suficiente.
Nick F
4

Aqui está minha solução, que não requer a definição de classes nos elementos filho:

.flex-inline-row {
    display: inline-flex;
    flex-direction: row;
}

.flex-inline-row.flex-spacing-4px > :not(:last-child) {
    margin-right: 4px;
}

Uso:

<div class="flex-inline-row flex-spacing-4px">
  <span>Testing</span>
  <span>123</span>
</div>

A mesma técnica pode ser usada para linhas e colunas flexíveis normais, além do exemplo embutido fornecido acima, e estendida com classes para espaçamento diferente de 4px.

MK10
fonte
4

Costumo usar o operador + para esses casos

#box {
  display: flex;
  width: 100px;
}
.item {
  background: gray;
  width: 50px;
  height: 50px;
}
.item + .item {
    margin-left: 5px;
}
<div id='box'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

wutzebaer
fonte
3

Acho que a maneira mais fácil de fazer isso é com porcentagens e apenas permitindo que a margem calcule sua largura

Isso significa que você acaba com algo assim se estiver usando seu exemplo

#box {
   display: flex;
}

.item {
   flex: 1 1 23%;
   margin: 0 1%;
}

Significa que seus valores são baseados na largura, o que pode não ser bom para todos.

lukefrake
fonte
Acabei de encontrar esta solução e sim, é muito bom. Funciona no meu caso, pelo menos (uma caneta para quem pode achar interessante: codepen.io/rishatmuhametshin/pen/XXjpaV ).
rishat
2

Aqui está uma grade de elementos da interface do usuário do cartão com espaçamento concluído usando a caixa flexível:

insira a descrição da imagem aqui

Fiquei frustrado com o espaçamento manual dos cartões, manipulando o preenchimento e as margens com resultados duvidosos. Então, aqui estão as combinações de atributos CSS que achei muito eficazes:

.card-container {
  width: 100%;
  height: 900px;
  overflow-y: scroll;
  max-width: inherit;
  background-color: #ffffff;
  
  /*Here's the relevant flexbox stuff*/
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: flex-start;
  flex-wrap: wrap; 
}

/*Supplementary styles for .card element*/
.card {
  width: 120px;
  height: 120px;
  background-color: #ffeb3b;
  border-radius: 3px;
  margin: 20px 10px 20px 10px;
}
<section class="card-container">
        <div class="card">

        </div>
        <div class="card">

        </div>
        <div class="card">

        </div>
        <div class="card">

        </div>
      </section>

Espero que isso ajude as pessoas, presente e futuro.

buildpax
fonte
Atualização: esse espaçamento é eficaz para elementos HTML de renderização móvel que precisam de um certo alinhamento (por exemplo, centro, esquerda, etc.). Se você se encontra usando o flex box para desenvolvimento móvel, encontrei alívio ao mudar para o alinhamento puramente baseado em margem.
Buildpax #
2

Columnify - Uma classe individual para N colunas

Flexbox e SCSS

.columnify {
  display: flex;

  > * {
    flex: 1;

    &:not(:first-child) {
      margin-left: 2rem;
    }
  }
}

Flexbox e CSS

.columnify {
  display: flex;
}

.columnify > * {
  flex: 1;
}

.columnify > *:not(:first-child) {
  margin-left: 2rem;
}
<div class="columnify">
  <div style="display: inline-block; height: 20px; background-color: blue;"></div>
  <div style="display: inline-block; height: 20px; background-color: blue"></div>
  <div style="display: inline-block; height: 20px; background-color: blue"></div>
</div>

Jogue com ele no JSFiddle .

zurfyx
fonte
1

#box {
  display: flex;
  width: 100px;
}
.item {
  background: gray;
  width: 50px;
  height: 50px;
}
/* u mean utility */
.u-gap-10 > *:not(:last-child) {
  margin-right: 10px;
}
<div id='box' class="u-gap-10">
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

Amo Wu
fonte
1

Basta usar .item + .itemno seletor para combinar com o segundo.item

#box {
  display: inline-flex;
  margin: 0 -5px;
}
.item {
  background: gray;
  width: 10px;
  height: 50px;
}

#box .item + .item {
  margin-left: 10px;
}
<div id='box'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
</div>

Andrew Luca
fonte
1

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 cada item, exceto no 1º, 5º e 9º itens, e assim por diante; e defina a largura fixa em cada item. Se a margem esquerda for 10 px, cada linha terá uma margem de 30 px entre 4 itens, a largura percentual do item poderá ser calculada da seguinte maneira:

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;
  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>

Salman A
fonte
1

De fato, existe uma maneira agradável, organizada e apenas de CSS de fazer isso (que pode ser considerado "melhor").

De todas as respostas postadas aqui, encontrei apenas uma que usa calc () com sucesso (de Dariusz Sikorski). Mas quando colocado com: "mas falha se houver apenas 2 itens na última linha", não houve solução expandida.

Esta solução aborda a questão do OP com uma alternativa às margens negativas e aborda o problema colocado para Dariusz.

notas:

  • Este exemplo demonstra apenas um layout de 3 colunas
  • Ele usa calc()para permitir que o navegador faça contas da maneira que deseja - 100%/3 (embora 33,3333% devam funcionar da mesma maneira) e (1em/3)*2 (embora .66em também deva funcionar bem) .
  • Ele usa ::afterpara preencher a última linha se houver menos elementos do que colunas

.flex-container {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
}
.flex-container:after {
  content: "";
}
.flex-container > div,
.flex-container:after {
  box-sizing: border-box;
  width: calc((100%/3) - ((1em/3)*2));
}
.flex-container > :nth-child(n + 4) {
  margin-top: 1em;
}

/* the following is just to visualize the items */
.flex-container > div,
.flex-container:after {
  font-size: 2em;
}
.flex-container {
  margin-bottom:4em;
}
.flex-container > div {
  text-align: center;
  background-color: #aaa;
  padding: 1em;
}
.flex-container:after {
  border: 1px dashed red;
}
<h2>Example 1 (2 elements)</h2>
<div class="flex-container">
  <div>1</div>
  <div>2</div>
</div>

<h2>Example 2 (3 elements)</h2>
<div class="flex-container">
  <div>1</div>
  <div>2</div>
  <div>3</div>
</div>

Também em https://codepen.io/anon/pen/rqWagE

aequalsb
fonte
1

Você poderia usar a nova propriedade gap. Copio e colo a explicação que encontrei neste artigo , além de mais informações

O layout da grade CSS teve uma lacuna (anteriormente, uma lacuna na grade) há algum tempo. Ao especificar o espaçamento interno de um elemento contendo, em vez do espaçamento em torno dos elementos filhos, o gap resolve muitos problemas comuns de layout. Por exemplo, com gap, você não precisa se preocupar com as margens nos elementos filho, causando espaços em branco indesejados nas bordas de um elemento que contém:

Infelizmente, no momento, apenas o FireFox suporta lacunas nos layouts flexíveis.

@use postcss-preset-env {
  stage: 0;
  browsers: last 2 versions
}

section {
  width: 30vw;
  
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(12ch, 1fr));
  
  &[flex] {
    display: flex;
    flex-wrap: wrap;
  }
  
  margin-bottom: 3rem;
}

.tag {
  color: white;
  background: hsl(265 100% 47%);
  padding: .5rem 1rem;
  border-radius: 1rem;
}

button {
  display: inline-flex;
  place-items: center;
  gap: .5rem;
  background: hsl(265 100% 47%);
  border: 1px solid hsl(265 100% 67%);
  color: white;
  padding: 1rem 2rem;
  border-radius: 1rem;
  font-size: 1.25rem;
}

body {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
<section>
  <h1>Grid</h1> 
  <div class="tag">Awesome</div>
  <div class="tag">Coo</div>
  <div class="tag">Rad</div>
  <div class="tag">Math</div>
</section>
<br>
<section flex>
  <h1>Flex</h1>
  <div class="tag">Awesome</div>
  <div class="tag">Coo</div>
  <div class="tag">Rad</div>
  <div class="tag">Math</div>
</section>

Andres Paul
fonte
gapjá foi recomendado em uma resposta aqui stackoverflow.com/a/58041749/2756409 Além disso, isso não é CSS.
TylerH
0

Não funcionará em todos os casos, mas se você tiver larguras filho flexíveis (%) e souber o número de itens por linha, poderá especificar de maneira muito limpa as margens dos elementos necessários usando o nth-child(s) seletor (es).

Depende em grande parte do que você quer dizer com "melhor". Dessa maneira, não é necessária marcação adicional do wrapper para elementos filhos ou elementos negativos - mas essas coisas têm seu lugar.

section {
  display: block
  width: 100vw;
}
.container {
  align-content: flex-start;
  align-items: stretch;
  background-color: #ccc;
  display: flex;
  flex-flow: row wrap;
  justify-content: flex-start;
  width: 100%;
}

.child-item {
  background-color: #c00;
  margin-bottom: 2%;
  min-height: 5em;
  width: 32%;
}

.child-item:nth-child(3n-1) {
  margin-left: 2%;
  margin-right: 2%;
}
<html>
  <body>
      <div class="container">
        <div class="child-item"></div>
        <div class="child-item"></div>
        <div class="child-item"></div>
        <div class="child-item"></div>
        <div class="child-item"></div>
        <div class="child-item"></div>
        <div class="child-item"></div>
      </div>
   </body>
</html>

jnmrobinson
fonte
Não responde. Funciona apenas para pai de largura fixa.
Verde
1
O OP não pede uma solução responsiva e o exemplo deles usa uma largura de correção. Dado que isso usa% values, é fácil argumentar que isso é responsivo, pois os itens se adaptarão ao tamanho do pai, que é definido por porcentagem.
Jnmrobinson 18/08
0

Eu me deparei com o mesmo problema anteriormente, então me deparei com a resposta para isso. Espero que ajude outras pessoas para referência futura.

resposta longa, adicione uma borda aos itens flexíveis do seu filho. então você pode especificar margens entre itens flexíveis para o que quiser. No snippet, eu uso preto para fins de ilustração, você pode usar 'transparent' se quiser.

#box {
  display: flex;
  width: 100px;
  /* margin: 0 -5px; *remove this*/
}
.item {
  background: gray;
  width: 50px;
  height: 50px;
  /* margin: 0 5px; *remove this*/
  border: 1px solid black; /* add this */
}
.item.special{ margin: 0 10px; }
<div id='box'>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item'></div>
  <div class='item special'></div>
</div>

Tunasing
fonte
0

O truque da margem negativa no contêiner de caixa funciona muito bem. Aqui está outro exemplo que funciona muito bem com pedidos, embalagens e o que não.

.container {
   border: 1px solid green;
   width: 200px;
   display: inline-block;
}

#box {
  display: flex;
  flex-wrap: wrap-reverse;
  margin: -10px;
  border: 1px solid red;
}
.item {
  flex: 1 1 auto;
  order: 1;
  background: gray;
  width: 50px;
  height: 50px;
  margin: 10px;
  border: 1px solid blue;
}
.first {
  order: 0;
}
<div class=container>
<div id='box'>
  <div class='item'>1</div>
  <div class='item'>2</div>
  <div class='item first'>3*</div>
  <div class='item'>4</div>
  <div class='item'>5</div>
</div>
</div>

cghislai
fonte