如何将包装弹性项目显示为 space-between 最后一行左对齐?
How to display wrapping flex items as space-between with last row aligned left?
我有一个固定宽度的容器,其中必须在一行中出现几个可变宽度的元素,这些元素可以根据需要溢出到其他行中。
但是,每个元素的开头必须与其顶部的元素对齐,因此在 ASCII 艺术中它看起来像这样(例如,填充 1):
/----------------------------------\
| |
| # One # Two # Three # Four |
| # Five # Six |
| |
\----------------------------------/
换句话说:
- 每行的第一个元素必须左对齐
- 每行的最后一个元素(最后一行除外)必须右对齐
- 每个元素都必须与其上方的元素左对齐
我正在尝试为此使用 flexbox 但没有成功。
This 是迄今为止最好的,对容器使用 flex-wrap: wrap
,对元素使用 flex-grow: 1
。
问题是最后一行填满了边缘。
justify-content: flex-start; // this does nothing
如果我拿走 flow-grow: 1
则元素分布不均。我也尝试在元素上摆弄 last-of-type
但这还不够。
flexbox
甚至可以做到这一点,还是我做错了?
所以,你有一个容器和一些东西吗?
<div class="container">
<span>msg1</span>
<span>msg1</span>
<span>msg1</span>
<span>msg1</span>
<span>msg1</span>
</div>
这就是它的工作原理,当您为您的容器声明 display: flex
时,它的所有直接子级也将变为 flex,并带有一些默认配置 (align-items:strech
)。
我猜你已经知道了,所以,也许你可以尝试使用 justify-content: space-between
,它会在行中对齐你的项目,让它们等间距加上 flex-basis: 25%
(以证明总会有连续 4 个项目,根据需要更改 de %)应该适用于除最后一行之外的所有行。对于最后一个,您可以使用 css 选择器(如 last-child
)并将其 属性 设置为 flex-grow: 0
/ flex-shrink:0
(解决您的问题之一,如果你使用 flex: 1 1 25%
而不是 flex-basis
) 以及 align-self: flex-start
或任何你喜欢的
在尝试了此处的建议(谢谢!)并广泛搜索网络后,我得出的结论是 flexbox 根本不可能做到这一点。 Any by that I mean 其他人已经得出了这个结论,而我却固执地试图让它发挥作用,直到最终放弃并接受更聪明的人的智慧。
我发现有几个链接可能会更好地解释它,或者要求的不同方面,所以我将它们张贴在这里以供...后代使用。
How to keep wrapped flex-items the same width as the elements on the previous row?
http://fourkitchens.com/blog/article/responsive-multi-column-lists-flexbox
我知道我有点晚了,但我在过去一个小时左右一直在寻找解决方案,我想我有点想通了。将空的 div
放在容器的末尾,并为其设置 flex-grow: 1
,仅此而已。同时在容器上设置 justify-content: space-between
,不要在其他项目上使用 flex-grow
。这将始终使最后一行左对齐,因为此 div 将延伸到所有剩余的 space.
然而,这个问题是它总是让最后一行左对齐——即使它是唯一的一行,这使得这个解决方案对我来说无法使用,但它可能对那些期望不止一行的人有用项目数。
如果项目的宽度是固定的,您可以在项目列表的末尾添加几个空的 div:
<div class="item">meaningful content</div>
<div class="item">meaningful content</div>
<div class="item">meaningful content</div>
<div class="empty-div"></div>
<div class="empty-div"></div>
<div class="empty-div"></div>
然后:
.item, .empty-div{ width: 150px; } // make them the same width
效果很好。
我只是偶然发现了同样的问题并想出了另一个解决方案。我不能决定它是有点脏还是有点优雅,但你自己决定。
向容器中添加与每行最大项目数一样多的空 div
,为它们分配与行项目相同的 class,但删除它们的任何边距或填充(基本上任何内容这给了他们一个高度)。这将导致该行按预期运行,因为在最后一行项目之后,总会有足够的不可见 "spacers" 来填充该行。被包裹到下一行的那些没有高度,因此它们不应影响页面的其余部分。
此处示例:
https://jsfiddle.net/amknwjmj/
.products {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.product {
/* set top and bottom margin only, as left and right
will be handled by space-between */
margin: 0.25rem 0;
/* account your desired margin two times and substract
it from the base width of the row item */
flex-basis: calc(25% - (0.25rem * 2));
}
.product.spacer {
/* remove all properties increasing the element height
from the spacers to avoid them being visible */
margin: 0;
padding: 0;
height: initial;
}
/* start demo styles (purely eye-candy not required for this to work) */
* {
box-sizing: border-box;
font-family: sans-serif;
}
.products {
padding: .25rem .5rem;
background: powderblue;
}
.product {
height: 75px;
line-height: 75px;
padding: .25rem;
text-align: center;
background: steelblue;
color: #fff;
}
.product.spacer {
background: none;
/* of course, spacers should NOT have a border
but they are helpful to illstrate what's going on. */
border: 1px dashed gray;
}
/* end demo styles */
<div class="products">
<article id="product-1" class="product">P1</article>
<article id="product-2" class="product">P2</article>
<article id="product-3" class="product">P3</article>
<article id="product-4" class="product">P4</article>
<article id="product-5" class="product">P5</article>
<div class="product spacer"></div>
<div class="product spacer"></div>
<div class="product spacer"></div>
<div class="product spacer"></div>
</div>
你可以试试用伪元素固定:
.container {
display:flex;
justify-content:space-between;
}
.container:after {
content: '';
flex-grow: 0;
width: 25%;
}
.container .element {
width: 25%;
}
使用 flexbox 没有简单的方法来做到这一点。但是如果你愿意牺牲 IE 那么你可以用 css grid
来完成,将这个添加到容器中:
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
如果你想在元素之间添加一些 space 然后添加
grid-gap: 10px;
我能够通过正负边距的组合获得预期的结果。
如果容器中的每个元素都定义了边距以在它们之间创建 space:
.container .element {
flex: 1;
margin: 0px 5px;
}
从容器中每行的边缘恢复像素,负边距相同:
.container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin: 0px -5px;
}
这应该导致行中的每个元素与容器边缘的每行的第一个和最后一个元素之间的距离为 10px。
我遇到了同样的问题,其实很简单。不需要放一些
SCSS 和或 jQuery.
您只需指定 "square" 的最大数量,然后取模即可知道该数量是否与您的 maxNumber 匹配。如果不是,你只需要定义一个快速函数来增加你的数字直到模数 return 0。
有了号码后,您只需循环 html。
对我来说,我在 ReactNative 上编码:
const RenderInvisibleSquare = (nb) => {
let tab = [];
let i = 1;
for (; (nb + i) % 3 !== 0; i++) {}
for (let n = 0; n < i; n++) {
tab.push(<View style={{ width: 120, height: 120, backgroundColor: 'red' }}/>);
}
return tab;
};
<ScrollView>
{
data.map(item => (
<View>
<View style={{ marginVertical: 5 }}>
<Text style={{ textAlign: 'center', color: '#7E8BF5' }}>{item.title}</Text>
</View>
<View style={{ flex: 1, flexWrap: 'wrap', alignItems: 'center', justifyContent: 'space-around', flexDirection: 'row' }}>
{
item.data.map(elem => (
<View style={{ width: 120, height: 120, marginBottom: 10, backgroundColor: 'red' }} />
))
}
{ item.data.length % 3 !== 0 && RenderInvisibleSquare(item.data.length)}
</View>
</View>
))
}
</ScrollView>
如果您不想要内容 (backgroundColor: 'red') 在我的情况下,您只需要制作它 'transparent'.
一种适用于许多情况的解决方案是简单地将 padding
应用于项目。然后你可以使用 flex-start
,并在卡片之间获得间距。
例如
.container {
display: flex;
justify-content: center;
}
.parent {
width: 420px;
display: flex;
flex-wrap: wrap;
flex-direction: row;
justify-content: flex-start;
}
.child {
flex: 0 30%;
min-width: 100px;
padding-left: 10px;
margin-bottom: 10px;
}
.child-content {
background-color: yellow;
border: 1px solid black;
height: 100px;
}
<div class="container">
<div class="parent">
<div class="child">
<div class="child-content">
Box
</div>
</div>
<div class="child">
<div class="child-content">
Box
</div>
</div>
<div class="child">
<div class="child-content">
Box
</div>
</div>
<div class="child">
<div class="child-content">
Box
</div>
</div>
<div class="child">
<div class="child-content">
Box
</div>
</div>
</div>
</div>
您可以通过执行以下操作在 flex-wrap 行中除最后一项之外的每个项目上指定 margin-right
:
.item:not(:nth-child(4n)) {
margin-right: 20px;
}
CSS Flex 4 列始终从左侧开始。我看不出来这不可能?如果列应该 等于 ,这 为我们工作 使用 calc()
和相对单位:
/* parent */
.ua-flex {
display: flex;
flex-wrap: wrap;
justify-content: start;
}
/* children */
.ua-flex > * {
flex: 0 0 calc(25% - 1em);
margin: 1em 0 0 0;
}
.ua-flex > :not(:nth-child(4n+4)) {
margin-right: 1.333333em;
}
我是不是漏掉了什么?它的所有关于数学,在这种情况下减去 calc() 1em,在 4 列中的 3 列上给出 3 space 的间隙 1.333em 和 margin-right,而 0.5em 减去 calc() 应该给出 0.666em 间隙与边距-在 4 列中的第 3 列上。
希望这对你有用...
我有一个固定宽度的容器,其中必须在一行中出现几个可变宽度的元素,这些元素可以根据需要溢出到其他行中。
但是,每个元素的开头必须与其顶部的元素对齐,因此在 ASCII 艺术中它看起来像这样(例如,填充 1):
/----------------------------------\
| |
| # One # Two # Three # Four |
| # Five # Six |
| |
\----------------------------------/
换句话说:
- 每行的第一个元素必须左对齐
- 每行的最后一个元素(最后一行除外)必须右对齐
- 每个元素都必须与其上方的元素左对齐
我正在尝试为此使用 flexbox 但没有成功。
This 是迄今为止最好的,对容器使用 flex-wrap: wrap
,对元素使用 flex-grow: 1
。
问题是最后一行填满了边缘。
justify-content: flex-start; // this does nothing
如果我拿走 flow-grow: 1
则元素分布不均。我也尝试在元素上摆弄 last-of-type
但这还不够。
flexbox
甚至可以做到这一点,还是我做错了?
所以,你有一个容器和一些东西吗?
<div class="container">
<span>msg1</span>
<span>msg1</span>
<span>msg1</span>
<span>msg1</span>
<span>msg1</span>
</div>
这就是它的工作原理,当您为您的容器声明 display: flex
时,它的所有直接子级也将变为 flex,并带有一些默认配置 (align-items:strech
)。
我猜你已经知道了,所以,也许你可以尝试使用 justify-content: space-between
,它会在行中对齐你的项目,让它们等间距加上 flex-basis: 25%
(以证明总会有连续 4 个项目,根据需要更改 de %)应该适用于除最后一行之外的所有行。对于最后一个,您可以使用 css 选择器(如 last-child
)并将其 属性 设置为 flex-grow: 0
/ flex-shrink:0
(解决您的问题之一,如果你使用 flex: 1 1 25%
而不是 flex-basis
) 以及 align-self: flex-start
或任何你喜欢的
在尝试了此处的建议(谢谢!)并广泛搜索网络后,我得出的结论是 flexbox 根本不可能做到这一点。 Any by that I mean 其他人已经得出了这个结论,而我却固执地试图让它发挥作用,直到最终放弃并接受更聪明的人的智慧。
我发现有几个链接可能会更好地解释它,或者要求的不同方面,所以我将它们张贴在这里以供...后代使用。
How to keep wrapped flex-items the same width as the elements on the previous row?
http://fourkitchens.com/blog/article/responsive-multi-column-lists-flexbox
我知道我有点晚了,但我在过去一个小时左右一直在寻找解决方案,我想我有点想通了。将空的 div
放在容器的末尾,并为其设置 flex-grow: 1
,仅此而已。同时在容器上设置 justify-content: space-between
,不要在其他项目上使用 flex-grow
。这将始终使最后一行左对齐,因为此 div 将延伸到所有剩余的 space.
然而,这个问题是它总是让最后一行左对齐——即使它是唯一的一行,这使得这个解决方案对我来说无法使用,但它可能对那些期望不止一行的人有用项目数。
如果项目的宽度是固定的,您可以在项目列表的末尾添加几个空的 div:
<div class="item">meaningful content</div>
<div class="item">meaningful content</div>
<div class="item">meaningful content</div>
<div class="empty-div"></div>
<div class="empty-div"></div>
<div class="empty-div"></div>
然后:
.item, .empty-div{ width: 150px; } // make them the same width
效果很好。
我只是偶然发现了同样的问题并想出了另一个解决方案。我不能决定它是有点脏还是有点优雅,但你自己决定。
向容器中添加与每行最大项目数一样多的空 div
,为它们分配与行项目相同的 class,但删除它们的任何边距或填充(基本上任何内容这给了他们一个高度)。这将导致该行按预期运行,因为在最后一行项目之后,总会有足够的不可见 "spacers" 来填充该行。被包裹到下一行的那些没有高度,因此它们不应影响页面的其余部分。
此处示例: https://jsfiddle.net/amknwjmj/
.products {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.product {
/* set top and bottom margin only, as left and right
will be handled by space-between */
margin: 0.25rem 0;
/* account your desired margin two times and substract
it from the base width of the row item */
flex-basis: calc(25% - (0.25rem * 2));
}
.product.spacer {
/* remove all properties increasing the element height
from the spacers to avoid them being visible */
margin: 0;
padding: 0;
height: initial;
}
/* start demo styles (purely eye-candy not required for this to work) */
* {
box-sizing: border-box;
font-family: sans-serif;
}
.products {
padding: .25rem .5rem;
background: powderblue;
}
.product {
height: 75px;
line-height: 75px;
padding: .25rem;
text-align: center;
background: steelblue;
color: #fff;
}
.product.spacer {
background: none;
/* of course, spacers should NOT have a border
but they are helpful to illstrate what's going on. */
border: 1px dashed gray;
}
/* end demo styles */
<div class="products">
<article id="product-1" class="product">P1</article>
<article id="product-2" class="product">P2</article>
<article id="product-3" class="product">P3</article>
<article id="product-4" class="product">P4</article>
<article id="product-5" class="product">P5</article>
<div class="product spacer"></div>
<div class="product spacer"></div>
<div class="product spacer"></div>
<div class="product spacer"></div>
</div>
你可以试试用伪元素固定:
.container {
display:flex;
justify-content:space-between;
}
.container:after {
content: '';
flex-grow: 0;
width: 25%;
}
.container .element {
width: 25%;
}
使用 flexbox 没有简单的方法来做到这一点。但是如果你愿意牺牲 IE 那么你可以用 css grid
来完成,将这个添加到容器中:
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
如果你想在元素之间添加一些 space 然后添加
grid-gap: 10px;
我能够通过正负边距的组合获得预期的结果。
如果容器中的每个元素都定义了边距以在它们之间创建 space:
.container .element {
flex: 1;
margin: 0px 5px;
}
从容器中每行的边缘恢复像素,负边距相同:
.container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin: 0px -5px;
}
这应该导致行中的每个元素与容器边缘的每行的第一个和最后一个元素之间的距离为 10px。
我遇到了同样的问题,其实很简单。不需要放一些 SCSS 和或 jQuery.
您只需指定 "square" 的最大数量,然后取模即可知道该数量是否与您的 maxNumber 匹配。如果不是,你只需要定义一个快速函数来增加你的数字直到模数 return 0。
有了号码后,您只需循环 html。 对我来说,我在 ReactNative 上编码:
const RenderInvisibleSquare = (nb) => {
let tab = [];
let i = 1;
for (; (nb + i) % 3 !== 0; i++) {}
for (let n = 0; n < i; n++) {
tab.push(<View style={{ width: 120, height: 120, backgroundColor: 'red' }}/>);
}
return tab;
};
<ScrollView>
{
data.map(item => (
<View>
<View style={{ marginVertical: 5 }}>
<Text style={{ textAlign: 'center', color: '#7E8BF5' }}>{item.title}</Text>
</View>
<View style={{ flex: 1, flexWrap: 'wrap', alignItems: 'center', justifyContent: 'space-around', flexDirection: 'row' }}>
{
item.data.map(elem => (
<View style={{ width: 120, height: 120, marginBottom: 10, backgroundColor: 'red' }} />
))
}
{ item.data.length % 3 !== 0 && RenderInvisibleSquare(item.data.length)}
</View>
</View>
))
}
</ScrollView>
如果您不想要内容 (backgroundColor: 'red') 在我的情况下,您只需要制作它 'transparent'.
一种适用于许多情况的解决方案是简单地将 padding
应用于项目。然后你可以使用 flex-start
,并在卡片之间获得间距。
例如
.container {
display: flex;
justify-content: center;
}
.parent {
width: 420px;
display: flex;
flex-wrap: wrap;
flex-direction: row;
justify-content: flex-start;
}
.child {
flex: 0 30%;
min-width: 100px;
padding-left: 10px;
margin-bottom: 10px;
}
.child-content {
background-color: yellow;
border: 1px solid black;
height: 100px;
}
<div class="container">
<div class="parent">
<div class="child">
<div class="child-content">
Box
</div>
</div>
<div class="child">
<div class="child-content">
Box
</div>
</div>
<div class="child">
<div class="child-content">
Box
</div>
</div>
<div class="child">
<div class="child-content">
Box
</div>
</div>
<div class="child">
<div class="child-content">
Box
</div>
</div>
</div>
</div>
您可以通过执行以下操作在 flex-wrap 行中除最后一项之外的每个项目上指定 margin-right
:
.item:not(:nth-child(4n)) {
margin-right: 20px;
}
CSS Flex 4 列始终从左侧开始。我看不出来这不可能?如果列应该 等于 ,这 为我们工作 使用 calc()
和相对单位:
/* parent */
.ua-flex {
display: flex;
flex-wrap: wrap;
justify-content: start;
}
/* children */
.ua-flex > * {
flex: 0 0 calc(25% - 1em);
margin: 1em 0 0 0;
}
.ua-flex > :not(:nth-child(4n+4)) {
margin-right: 1.333333em;
}
我是不是漏掉了什么?它的所有关于数学,在这种情况下减去 calc() 1em,在 4 列中的 3 列上给出 3 space 的间隙 1.333em 和 margin-right,而 0.5em 减去 calc() 应该给出 0.666em 间隙与边距-在 4 列中的第 3 列上。
希望这对你有用...