如何集中一个弹性容器,但左对齐弹性项目

我想要的 Flex 项目是居中的,但当我们有第二行,有5(从下图)1下,而不是居中的父。

enter image description here

这里有一个例子:

ul {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
margin: 0;
padding: 0;
}
li {
list-style-type: none;
border: 1px solid gray;
margin: 15px;
padding: 5px;
width: 200px;
}
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
</ul>

Http://jsfiddle.net/8jqbjese/2/

87958 次浏览

Flexbox 挑战与限制

挑战是将一组弹性项目集中在一起,并将它们左对齐到包装上。但是,除非每行有固定数量的盒子,并且每个盒子是固定宽度的,否则目前不可能使用 Flexbox。

使用问题中发布的代码,我们可以创建一个新的 flex 容器来包装当前的 flex 容器(ul) ,这将允许我们使用 justify-content: centerul居中。

然后,ul的伸缩项可以与 justify-content: flex-start左对齐。

#container {
display: flex;
justify-content: center;
}


ul {
display: flex;
justify-content: flex-start;
}

这将创建一组居中的左对齐的 Flex 项。

这种方法的问题在于,在特定的屏幕尺寸下,在 ul的右侧会出现一个间隙,使其不再显示在中心位置。

enter image description here enter image description here

这是因为在 Flex 布局(实际上是一般的 CSS)中,容器是:

  1. 不知道元素什么时候包装;
  2. 不知道以前占用的空间现在是空的
  3. 不会重新计算它的宽度,以缩小包装较窄的布局。

右边空格的最大长度是容器期望在那里的 Flex 项的长度。

在下面的演示中,通过水平调整窗口大小,您可以看到空白来来去去。

演示


更实际的方法

使用 inline-block媒体查询可以在没有柔性箱的情况下实现所需的布局。

超文本标示语言

<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
</ul>

CSS

ul {
margin: 0 auto;                  /* center container */
width: 1200px;
padding-left: 0;                 /* remove list padding */
font-size: 0;                    /* remove inline-block white space;
see https://stackoverflow.com/a/32801275/3597276 */
}


li {
display: inline-block;
font-size: 18px;                 /* restore font size removed in container */
list-style-type: none;
width: 150px;
height: 50px;
line-height: 50px;
margin: 15px 25px;
box-sizing: border-box;
text-align: center;
}


@media screen and (max-width: 430px) { ul { width: 200px; } }
@media screen and (min-width: 431px) and (max-width: 630px) { ul { width: 400px; } }
@media screen and (min-width: 631px) and (max-width: 830px) { ul { width:600px;  } }
@media screen and (min-width: 831px) and (max-width: 1030px) { ul { width: 800px; } }
@media screen and (min-width: 1031px) and (max-width: 1230px) { ul { width: 1000px; } }

上面的代码呈现一个具有左对齐子元素的水平居中的容器,如下所示:

enter image description here

演示


其他选择

正如@michael 建议的那样,这是当前 Flexbox 的一个局限。但是如果您仍然希望使用 flexjustify-content: center;,那么我们可以通过添加一个虚拟的 li元素并分配 margin-left来解决这个问题。

    const handleResize = () => {
const item_box = document.getElementById('parentId')
const list_length  = item_box.clientWidth
const product_card_length = 200 // length of your child element
const item_in_a_row = Math.round(list_length/product_card_length)
const to_be_added = item_in_a_row - parseInt(listObject.length % item_in_a_row) // listObject is the total number items
const left_to_set = (to_be_added - 1 ) * product_card_length // -1 : dummy item has width set, so exclude it when calculating the left margin
const dummy_product = document.querySelectorAll('.product-card.dummy')[0]
dummy_product.style.marginLeft = `${left_to_set}px`
}
handleResize() // Call it first time component mount
window.addEventListener("resize", handleResize);

检查 小提琴(调整大小参见)供参考的录像

使用页边距获得所需样式的一种方法是执行以下操作:

#container {
display: flex;
justify-content: center;
}


#innercontainer {
display: flex;
flex: 0.9; -> add desired % of margin
justify-content: flex-start;
}

您可以使用 CSS 网格实现它,只需使用 repeat(autofit, minmax(width-of-the-element, max-content))

ul {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(210px, max-content));
grid-gap: 16px;
justify-content: center;
padding: initial;
}


li {
list-style-type: none;
border: 1px solid gray;
padding: 5px;
width: 210px;
}
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
</ul>

Http://jsfiddle.net/rwa20jkh/

我在使用 React Natural 编写代码时遇到了这个问题。使用 FlexBox 可以得到一个优雅的解决方案。在我的特殊情况下,我试图使用 alignItems 将三个 Flex 盒(Flex: 2)放在另一个盒子中。我想到的解决方案是使用两个空 s,每个 s 都带有 Flex: 1。

<View style=\{\{alignItems: 'center', flexWrap: 'wrap', flexDirection: 'row'}}>
<View style=\{\{flex: 1}} />
// Content here
<View style=\{\{flex: 1}} />
</View>

易于转换为 web/CSS。

您可以将不可见的元素放置在与其他元素相同的类中(为了显示目的,在示例中删除了这些元素) ,并将高度设置为0。这样,您就能够在网格的最开始对这些条目进行调整。

例子

<div class="table-container">
<div class="table-content">
<p class="table-title">Table 1</p>
<p class="mesa-price">$ 20</p>
</div>
  

<!-- Make stuff justified start -->
<div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
<div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
<div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
<div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
</div>

结果

enter image description here

我发现解决这个问题最简单的方法就是简单地添加一些具有可见性的位置持有者: hide。这样,它保持正确的间距,因为它包装。

不知为何,“乔82的回答对我不起作用。然而,我发现这是正确的方法。在阅读了 这个关于 auto-fitauto-fill的文章后,我发现自动拟合在可能的情况下会创建新的列; 然而,它会折叠它们,如果网格项的最大宽度允许它们这样做,那么网格项就会填满整个可用空间。

对于那些感兴趣的: auto-fill在可能的情况下也会创建新的列,但不会让它们折叠,因此它会创建空的可见列,这将占用空间。 您可以在下面的图像中看到这一点: 图片来源: img src = “ https://i.stack.imgur.com/yxfxR.gif”alt = “关于自动填充和自动适应的区别的说明”/>

因此,我对“ grid-template-column”使用 repeat(auto-fit, minmax(10rem, 1fr)

然后,我将 justify-items设置为 center,这样就可以在内联轴线上对齐网格区域内的项目。

我还需要在列和行之间添加一些“边距”,所以我用速记添加了 row-gap1remcolumn-gap

结果,我在 div 中添加了以下 CSS,其中包含网格项:

.card-section {
width: 100%;
display: grid;
justify-items: center;
gap: 1rem;
grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
}

我知道这并不完全是 OP 想要达到的,但是也许它能帮助一些人,他们和我有着相同的问题并且偶然发现了这个问题。