Flexbox:每行4个项目


260

我正在使用一个伸缩框来显示8个项目,这些项目将随我的页面动态调整大小。如何强制将项目分成两行?(每行4个)?

这是一个相关的片段:

(或者,如果您更喜欢jsfiddle- http://jsfiddle.net/vivmaha/oq6prk1p/2/

.parent-wrapper {
  height: 100%;
  width: 100%;
  border: 1px solid black;
}
.parent {
  display: flex;
  font-size: 0;
  flex-wrap: wrap;
  margin: -10px 0 0 -10px;
}
.child {
  display: inline-block;
  background: blue;
  margin: 10px 0 0 10px;
  flex-grow: 1;
  height: 100px;
}
<body>
  <div class="parent-wrapper">
    <div class="parent">
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
    </div>
  </div>
</body>


16
[更新]该问题基于不良的无响应设计。如果您使用以下答案之一,请当心。在一个好的设计中,您将在宽屏幕上拥有更多项目,而在较小的屏幕上拥有更少的项目。在所有屏幕尺寸上强制设置4个项目仅在狭窄的屏幕宽度范围内才具有吸引力。
Vivek Maharajh '18

Answers:


380

您已经flex-wrap: wrap在容器上了。很好,因为它会覆盖默认值nowrapsource)。这就是项目不包裹以形成网格的原因某些情况下

在这种情况下,主要问题在于flex-grow: 1弹性项目。

flex-grow属性实际上并没有设置弹性项目的大小。它的任务是在容器中分配可用空间(来源)中。因此,无论屏幕尺寸有多小,每一项都会在行中获得一定比例的可用空间。

更具体地说,您的容器中有八个flex项目。用flex-grow: 1,每个人将获得行中1/8的可用空间。由于您的项目中没有内容,因此它们可以缩小到零宽度并且永远不会包装。

解决方案是在项目上定义宽度。试试这个:

.parent {
  display: flex;
  flex-wrap: wrap;
}

.child {
  flex: 1 0 21%; /* explanation below */
  margin: 5px;
  height: 100px;
  background-color: blue;
}
<div class="parent">
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
</div>

用中flex-grow: 1定义flex简写中的不需要为flex-basis25%,由于边距,实际上每行将导致三项。

由于flex-grow将消耗行上的可用空间,因此flex-basis只需要足够大即可执行换行。在这种情况下,使用flex-basis: 21%,有足够的空间留出边距,但没有足够的空间容纳第五个项目。


1
我喜欢它是因为它对我有用,但是“足够的空间”使我感到有些不安。在某些微小的窗口或情况下,这种“估计”可能会使我失望吗?
杰克逊

1
什么样的情况?在大多数布局中,有些极端情况可能会造成问题。此类案例通常会通过成本效益分析进行分析,因为它们从未或几乎从未发生过。例如,在上面的解决方案中,如果您放置很大的边距,则布局可能会中断。如果这是一个问题,则应将其发布在问题中。@杰克逊
迈克尔·本杰明

2
“如果您留出很大的空白,则布局可能会破裂”,这是我要避免的情况的一个示例。我不在乎实用性;娱乐我对完美的崇拜。有什么方法可以更精确吗?
杰克逊

27
您也可以使用flex: 1 0 calc(25% - 10px);
MarkG '18

2
好答案!我使用的一个小改进margin: 2%;不是固定像素数,以防止盒子在小型设备/分辨率下跳到新的一行。通用公式是(100 - (4 * box-width-percent)) / 8不同盒子宽度的%
thomaspsk

104

.child元素添加宽度。margin-left如果您希望每行始终将其设置为4,我个人将使用百分比。

演示

.child {
    display: inline-block;
    background: blue;
    margin: 10px 0 0 2%;
    flex-grow: 1;
    height: 100px;
    width: calc(100% * (1/4) - 10px - 1px);
}

好主意。我对这个想法进行了少量修改。jsfiddle.net/vivmaha/oq6prk1p/6
Vivek Maharajh 2015年

1
啊。这实际上并不能解决我的问题。参见示例:jsfiddle.net/vivmaha/oq6prk1p/7。我没有使用百分比作为保证金的自由。它们必须是固定宽度。这意味着我们选择的不可思议的23%无法使用,因为它没有考虑固定边距。
Vivek Maharajh 2015年

3
是的,calc解决了!'calc(100%*(1/4)-10px-1px)'。参见jsfiddle.net/vivmaha/oq6prk1p/9
Vivek Maharajh,2015年

24
那么,flex在这方面有什么用呢?
twojr

那么响应式设计呢?我们不想为孩子设置固定的宽度
Candlejack,

40

这是另一种方法。

您也可以通过这种方式完成它:

.parent{
  display: flex;
  flex-wrap: wrap;
}

.child{
  width: 25%;
  box-sizing: border-box;
}

范例:https//codepen.io/capynet/pen/WOPBBm

还有一个更完整的示例:https : //codepen.io/capynet/pen/JyYaba


1
如果我的孩子少于四个怎么办?我不喜欢那个空白的空白区域,孩子对此没有反应...
Candlejack

Muddasir Abbas的另一个答案仅使用弹性设置,因此我认为这是一种更清洁的解决方案。
Andrew Koster

17

我会这样使用负边距和装订线来计算:

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

.child {
  width: calc(25% - 10px);
  margin-left: 10px;
  margin-top: 10px;
}

演示: https : //jsfiddle.net/9j2rvom4/


替代CSS网格方法:

.parent {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-column-gap: 10px;
  grid-row-gap: 10px;
}

演示: https //jsfiddle.net/jc2utfs3/


14
<style type="text/css">
.parent{
    display: flex;
    flex-wrap: wrap;
}
.parent .child{
    flex: 1 1 25%;
}
</style>    
<div class="parent">
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
    </div>

希望能帮助到你。有关更多详细信息,您可以点击此链接


4

我相信这个例子比@dowomenfart 更准,而且更容易理解

.child {
    display: inline-block;
    margin: 0 1em;
    flex-grow: 1;
    width: calc(25% - 2em);
}

在直接切成肉的同时,完成了相同的宽度计算。数学更容易,并且由于其可扩展性和移动友好性而em成为新标准


3
em并不是真正的新标准。这可能是一件痛苦的事,并且设计师在设计时就没有考虑到EM。
丹尼·范·霍尔滕

2

.parent-wrapper {
	height: 100%;
	width: 100%;
	border: 1px solid black;
}
	.parent {
	display: flex;
	font-size: 0;
	flex-wrap: wrap;
	margin-right: -10px;
	margin-bottom: -10px;
}
	.child {
	background: blue;
	height: 100px;
	flex-grow: 1;
	flex-shrink: 0;
	flex-basis: calc(25% - 10px);
}
	.child:nth-child(even) {
	margin: 0 10px 10px 10px;
	background-color: lime;
}
	.child:nth-child(odd) {
	background-color: orange; 
}
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	<style type="text/css">

	</style>
</head>
<body>
  <div class="parent-wrapper">
    <div class="parent">
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
    </div>
  </div>
</body>
</html>

;)


1
如果可以的话,请添加一些有关为什么它回答OP问题的上下文,而不仅仅是发布代码。
d219,18年

如果将其添加justify-content: space-evenly;到对象中,则它们可以很好地对齐,而不必calc在子对象上进行操作。不过,感谢您的示例!
Mattijs

0

软包装+负边距

为什么柔性主场迎战display: inline-block

为什么要负保证金?

您可以在边缘情况下使用SCSS或CSS-in-JS(即列中的第一个元素),或者设置默认边距并在以后消除外部边距。

实作

https://codepen.io/zurfyx/pen/BaBWpja

<div class="outerContainer">
    <div class="container">
        <div class="elementContainer">
            <div class="element">
            </div>
        </div>
        ...
    </div>
</div>
:root {
  --columns: 2;
  --betweenColumns: 20px; /* This value is doubled when no margin collapsing */
}

.outerContainer {
    overflow: hidden; /* Hide the negative margin */
}

.container {
    background-color: grey;
    display: flex;
    flex-wrap: wrap;
    margin: calc(-1 * var(--betweenColumns));
}

.elementContainer {
    display: flex; /* To prevent margin collapsing */
    width: calc(1/var(--columns) * 100% - 2 * var(--betweenColumns));
    margin: var(--betweenColumns);
}

.element {
    display: flex;
    border: 1px solid red;
    background-color: yellow;
    width: 100%;
    height: 42px;
}

-12

这是不使用的另一种方法calc()

// 4 PER ROW
// 100 divided by 4 is 25. Let's use 21% for width, and the remainder 4% for left & right margins...
.child {
  margin: 0 2% 0 2%;
  width: 21%;
}

// 3 PER ROW
// 100 divided by 3 is 33.3333... Let's use 30% for width, and remaining 3.3333% for sides (hint: 3.3333 / 2 = 1.66666)
.child {
  margin: 0 1.66666% 0 1.66666%;
  width: 30%;
}

// and so on!

这里的所有都是它的。您可以看中尺寸以获得更美观的尺寸,但这是个主意。


6
我没有对此进行测试,但是CSS语法是错误的(CSS值未加引号,并且声明应以分号结尾),因此它绝对不能以当前形式运行。
Nick F
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.