如何以最后一行左对齐的方式显示包装弹性项目?

时间:2015-12-17 09:34:44

标签: html css css3 flexbox

我有一个固定宽度的容器,其中几个可变宽度的元素必须出现在一行中,这可以根据需要溢出到其他行中。

但是,每个元素的开头必须与它上面的元素对齐,所以在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是否可以实现这一点,或者我是否采取了错误的方式?

10 个答案:

答案 0 :(得分:13)

在这里尝试了建议(谢谢!)并在网上搜索了很长时间后,我得出结论,这对于flexbox来说根本不可能。任何我认为其他人已经达成了这个结论,而我却顽固地试图让它继续工作,直到最后放弃并接受更聪明人的智慧。

我遇到的一些链接可能会更好地解释它,或者要求的不同方面,所以我将它们发布在这里......后代。

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

答案 1 :(得分:6)

我知道我有点迟了,但过去一小时左右我一直在寻找解决方案,我想我有点想通了。将空div放在容器的末尾,并将flex-grow: 1设置为它,而不是其他内容。同时在容器上设置justify-content: space-between,不要在其他项目上使用flex-grow。这将始终使最后一行对齐,因为此div将延伸到所有剩余空间。

然而问题是它始终使最后一行左对齐 - 即使它是唯一的一行,这使得该解决方案对我来说无法使用,但它可能适用于可以预期多行项目的人

答案 2 :(得分:2)

如果项目的宽度是固定的,您可以在项目列表的末尾添加几个空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

完美地运作。

答案 3 :(得分:2)

结合正负边距,我能够达到预期的结果。

如果容器中的每个元素都定义了一个边距以在它们之间创建一个空格:

.container .element {
   flex: 1;
   margin: 0px 5px;
}

从容器中每一行的边缘恢复像素,其负边距为相同量:

.container {
   display: flex;
   flex-direction: row;
   flex-wrap: wrap;
   margin: 0px -5px;
}

这将导致行中每个元素之间的距离为10px,每行的第一行和最后一行在容器的边缘。

答案 4 :(得分:1)

我偶然发现了同样的问题并提出了另一种解决方案。我不能决定它是否有点脏或优雅,而是自己决定。

将尽可能多的空div s作为每行的最大项目数添加到容器中,为它们分配与行项相同的类但删除任何边距或填充(基本上任何给它们高度的东西) 。这将导致行按预期运行,因为在最后一个行项之后,总会有足够的不可见“间隔符”来填充行。被包裹到下一行的那些没有高度,所以它们不应该影响页面的其余部分。

此处示例: 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>

答案 5 :(得分:0)

所以,你有一个容器和里面的东西?

<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或您喜欢的任何内容

答案 6 :(得分:0)

你可以尝试使用fixed-with-pseudo-element:

.container {
 display:flex;
 justify-content:space-between;
}
.container:after {
  content: '';
  flex-grow: 0;
  width: 25%;
}
.container .element {
  width: 25%;
}

答案 7 :(得分:0)

使用flexbox没有简单的方法。但是,如果您愿意牺牲IE,则可以使用CSS grid将其添加到容器中:

display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));

如果您要在元素之间留出一些空间,请添加

grid-gap: 10px;

答案 8 :(得分:0)

在许多情况下都可以使用的一种解决方案是将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>

答案 9 :(得分:-1)

我也面临着同样的问题,实际上这很简单。不用放一些 SCSS和或jQuery。

您只需要指定“ square”的最大数量,并取模以知道该数量是否与您的maxNumber相匹配。如果不是,则只需定义一个快速函数即可递增您的数字,直到该模返回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:“红色”),则只需将其设置为“透明”即可。