如何使Flex容器居中但左对齐flex项目

时间:2015-09-26 21:27:26

标签: html css css3 flexbox

我希望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>
&#13;
&#13;
&#13;

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

7 个答案:

答案 0 :(得分:57)

Flexbox Challenge&amp;限制

挑战在于将一组柔性物品居中并将它们左对齐。但除非每行有固定数量的盒子,并且每个盒子都是固定宽度的,所以目前这对于flexbox来说是不可能的。

使用问题中发布的代码,我们可以创建一个新的Flex容器来包装当前的Flex容器(ul),这样我们就可以使uljustify-content: center居中。

然后ul的弹性项目可以与justify-content: flex-start左对齐。

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

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

这将创建一个居中的左对齐弹性项目组。

此方法存在的问题是,在某些屏幕尺寸下,ul右侧会有间隙,使其不再显示为居中位置。

enter image description here enter image description here

这是因为在flex布局中(实际上,通常是CSS)容器:

  1. 不知道元素何时换行;
  2. 不知道以前占用的空间现在是空的,
  3. 不会重新计算其宽度以收缩包装较窄的布局。
  4. 右边的空格的最大长度是容器期望的弹性项目的长度。

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

    DEMO

    更实用的方法

    使用 inline-block 媒体查询,无需使用flexbox即可实现所需的布局。

    HTML

    <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

    DEMO

    其他选项

答案 1 :(得分:12)

您可以使用CSS Grid实现此功能,只需使用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/

答案 2 :(得分:0)

正如@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); 

选中此fiddle (resize and see )video for reference

答案 3 :(得分:0)

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

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

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

答案 4 :(得分:0)

您可以放置​​与其他类别相同的不可见元素(出于展示目的在示例中删除),并将高度设置为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

答案 5 :(得分:0)

在将内容居中放置在flex中时,我遇到了类似的问题。我尝试了很多技巧和修复,但是由于一个愚蠢的错误而无法正常工作。

如果在阅读了这些答案之后仍然没有人能够解决此问题,请尝试检查是否有愚蠢的错误。在我的情况下,这是一个span,其中flex-grow设置为1作为分隔符。

答案 6 :(得分:-1)

我在用React Native编码时遇到了这个问题。使用FlexBox可以找到一个优雅的解决方案。在我的特定情况下,我试图使用alignItems将三个伸缩框(Flex:2)居中放置在另一个框中。我想出的解决方案是使用两个empty,每个Flex都有:1。

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

易于转换为Web / CSS。