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
Better way to set distance between flexbox items
提问by Sasha Koss
To set the minimal distance between flexbox items I'm using margin: 0 5px
on .item
and margin: 0 -5px
on container. For me it seems like a hack, but I can't find any better way to do this.
要设置我在容器margin: 0 5px
上.item
和margin: 0 -5px
容器上使用的 flexbox 项目之间的最小距离。对我来说,这似乎是一种黑客行为,但我找不到更好的方法来做到这一点。
#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-spacing
for tables (except for CSS propertygap
which 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-child
and works without any modification on flex-wrap:wrap
is to set padding:5px
on the container and margin:5px
on the children. That will produce a 10px
gap between each child and between each child and their parent.
根据我的经验,不使用:first-child
/:last-child
并且无需任何修改即可工作的“最干净”的方式flex-wrap:wrap
是padding:5px
在容器和子项margin:5px
上设置。这将10px
在每个孩子之间以及每个孩子与其父母之间产生差距。
.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 的浏览器的工作解决方案。没有负利润。
.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 #box
wrapper.
下面的代码可以解决问题。在这种方法中,没有必要给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 10px
space 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 gap
property for Flexbox, although at this time (14 Nov 2019) it's only supported in Firefoxbut should be implemented in Chrome soon:
根据#ChromDevSummit,Flexbox有一个gap
属性的实现,尽管目前(2019 年 11 月 14 日)它仅在 Firefox 中受支持,但很快就会在 Chrome 中实现:
I will update my answer once it gets to Chrome too.
一旦它到达Chrome,我也会更新我的答案。