CSS 设置 flexbox 项目之间距离的更好方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20626685/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 01:20:16  来源:igfitidea点击:

Better way to set distance between flexbox items

cssflexbox

提问by Sasha Koss

To set the minimal distance between flexbox items I'm using margin: 0 5pxon .itemand margin: 0 -5pxon container. For me it seems like a hack, but I can't find any better way to do this.

要设置我在容器margin: 0 5px.itemmargin: 0 -5px容器上使用的 flexbox 项目之间的最小距离。对我来说,这似乎是一种黑客行为,但我找不到更好的方法来做到这一点。

Example

例子

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

采纳答案by Sasha Koss

  • Flexbox doesn't have collapsing margins.
  • Flexbox doesn't have anything akin to border-spacingfor tables (except for CSS property gapwhich isn't well supported in most browsers, caniuse)
  • Flexbox 没有折叠边距。
  • Flexbox 没有任何类似于border-spacing表格的东西(除了 CSS 属性gap,它在大多数浏览器中都没有得到很好的支持,caniuse

Therefore achieving what you are asking for is a bit more difficult.

因此,实现您所要求的要困难一些。

In my experience, the "cleanest" way that doesn't use :first-child/:last-childand works without any modification on flex-wrap:wrapis to set padding:5pxon the container and margin:5pxon the children. That will produce a 10pxgap between each child and between each child and their parent.

根据我的经验,不使用:first-child/:last-child并且无需任何修改即可工作的“最干净”的方式flex-wrap:wrappadding:5px在容器和子项margin:5px上设置。这将10px在每个孩子之间以及每个孩子与其父母之间产生差距。

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>

回答by Roumelis George

This is not a hack. The same technique is also used by bootstrap and its grid, though, instead of margin, bootstrap uses padding for its cols.

这不是黑客攻击。bootstrap 及其网格也使用相同的技术,但是,bootstrap 使用填充而不是边距来填充它的列。

.row {
  margin:0 -15px;
}
.col-xx-xx {
  padding:0 15px;
}

回答by Dariusz Sikorski

Flexbox and css calc with multiple rows support

支持多行的 Flexbox 和 css calc

Hello, below is my working solution for all browsers supporting flexbox. No negative margins.

您好,以下是我针对所有支持 flexbox 的浏览器的工作解决方案。没有负利润。

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>

Take a note this code can be shorter using SASS

请注意,使用 SASS 可以缩短此代码

Update 2020.II.11 Aligned columns on the last row to the left

更新 2020.II.11 最后一行向左对齐的列

Update 2020.II.14 Removed margin-bottom in the last row

更新 2020.II.14 删除了最后一行的 margin-bottom

回答by hexalys

You can use transparent borders.

您可以使用透明边框。

I have contemplated this issue while trying to build a flex grid model which can fallback to a tables + table-cell model for older browsers. And Borders for column gutters seemed to me the best appropriate choice. i.e. Table-cells don't have margins.

我在尝试构建一个 flex 网格模型时考虑过这个问题,该模型可以回退到旧浏览器的表格 + 表格单元模型。在我看来,列边沟的边框是最合适的选择。即表格单元格没有边距。

e.g.

例如

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

Also note that you need min-width: 50px;for flexbox. The flex model will not handle fixed sizes unless you do flex: none;on the particular child element you want as fixed and therefore excluded from being "flexi". http://jsfiddle.net/GLpUp/4/But all columns together with flex:none;is no longer a flex model. Here is something closer to a flex model: http://jsfiddle.net/GLpUp/5/

另请注意,您需要min-width: 50px;flexbox。flex 模型不会处理固定大小,除非您flex: none;对想要固定的特定子元素进行处理,因此将其排除在"flexi". http://jsfiddle.net/GLpUp/4/但是所有的列flex:none;都不再是 flex 模型。这是更接近 flex 模型的东西:http: //jsfiddle.net/GLpUp/5/

So you can actually use margins normally if you don't need the table-cell fallback for older browsers. http://jsfiddle.net/GLpUp/3/

因此,如果您不需要旧浏览器的表格单元回退,您实际上可以正常使用边距。http://jsfiddle.net/GLpUp/3/

Setting background-clip: padding-box;will be necessary when using a background, as otherwise the background will flow into the transparent border area.

background-clip: padding-box;使用背景时需要设置,否则背景会流入透明边框区域。

回答by weBBer

This solution will work for all cases even if there are multiple rows or any number of elements. But the count of the section should be same you want 4 in first row and 3 is second row it won't work that way the space for the 4th content will be blank the container won't fill.

即使有多行或任意数量的元素,此解决方案也适用于所有情况。但是该部分的计数应该与您想要的第一行 4 和第二行 3 的计数相同,这样就行不通了,第 4 个内容的空间将是空白的,容器不会填充。

We are using display: grid;and its properties.

我们正在使用 display: grid;及其属性。

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

The Downside of this method is in Mobile Opera Miniwill not be supported and in PC this works only after IE10.

这种方法的缺点是在 Mobile Opera Mini中将不受支持,并且在 PC 中这仅在IE10之后有效。

Note for complete browser compatability including IE11 please use Autoprefixer

注意包括 IE11 在内的完整浏览器兼容性请使用 Autoprefixer



OLD ANSWER

旧答案

Don't think of it as an old solution, it's still one of the best if you only want single row of elements and it will work with all the browsers.

不要认为它是一个旧的解决方案,如果您只想要单行元素,它仍然是最好的解决方案之一,并且它适用于所有浏览器。

This method is used by CSS sibling combination, so you can manipulate it many other ways also, but if your combination is wrong it may cause issues also.

此方法由CSS 兄弟组合使用,因此您也可以通过多种其他方式对其进行操作,但是如果您的组合错误,也可能会导致问题。

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

The below code will do the trick. In this method, there is no need to give margin: 0 -5px;to the #boxwrapper.

下面的代码可以解决问题。在这种方法中,没有必要给margin: 0 -5px;#box包装。

A working sample for you:

为您准备的工作示例:

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

回答by Do Async

You can use & > * + *as a selector to emulate a flex-gap(for a single line):

您可以& > * + *用作选择器来模拟flex-gap(对于单行):

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

If you need to support flex wrapping, you can use a wrapper element:

如果你需要支持flex wrapping,你可以使用一个 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>

回答by Stickers

Let's say if you want to set 10pxspace between the items, you can just set .item {margin-right:10px;}for all, and reset it on the last one .item:last-child {margin-right:0;}

假设你想10px在项目之间设置空间,你可以.item {margin-right:10px;}为所有设置,并在最后一个重置.item:last-child {margin-right:0;}

You can also use general sibling ~or next +sibling selector to set left margin on the items excluding the first one .item ~ .item {margin-left:10px;}or use .item:not(:last-child) {margin-right: 10px;}

您还可以使用通用兄弟~或下一个+兄弟选择器在除第一个之外的项目上设置左边距.item ~ .item {margin-left:10px;}或使用.item:not(:last-child) {margin-right: 10px;}

Flexbox is so clever that it automatically recalculates and equally distributes the grid.

Flexbox 非常聪明,它会自动重新计算并平均分配网格。

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>

If you want to allow flex wrap, see the following example.

如果要允许flex wrap,请参见以下示例。

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>

回答by Simon Epskamp

I have found a solution that is based on the general sibling selector, ~, and allows infinite nesting.

我找到了一个基于通用同级选择器的解决方案,~允许无限嵌套。

See this code pen for a working example

有关工作示例,请参阅此代码笔

Basically, inside of column containers, every child that is preceded by another child gets a top margin. Likewise, inside every row container, every child that is preceded by another gets a left margin.

基本上,在列容器内部,每个孩子前面的另一个孩子都有一个上边距。同样,在每个行容器内,每个在另一个之前的孩子都有一个左边距。

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

回答by chris

Moving on from sawa's answer, here's a slightly improved version that allows you to set a fixed spacing between the items without the surrounding margin.

从sawa的回答开始,这里有一个稍微改进的版本,它允许您在没有周围边距的情况下设置项目之间的固定间距。

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

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

Also included is the Safari "-webkit-flex" version.

还包括 Safari 的“-webkit-flex”版本。

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

回答by Eliya Cohen

According to #ChromDevSummitthere's an implementation of gapproperty for Flexbox, although at this time (14 Nov 2019) it's only supported in Firefoxbut should be implemented in Chrome soon:

根据#ChromDevSummitFlexbox有一个gap属性的实现,尽管目前(2019 年 11 月 14 日)它仅在 Firefox 中受支持,但很快就会在 Chrome 中实现:

enter image description here

在此处输入图片说明

Live Demo

现场演示

I will update my answer once it gets to Chrome too.

一旦它到达Chrome,我也会更新我的答案。