Flexbox 挑战:如何在整行中使用相同且均匀的边距进行换行

Posted

技术标签:

【中文标题】Flexbox 挑战:如何在整行中使用相同且均匀的边距进行换行【英文标题】:Flexbox challenge: how to get row wrapping with children identical and uniform margins in full rows 【发布时间】:2016-07-27 07:01:20 【问题描述】:

好的,所以我想使用 flexbox 创建一个由完全统一的子元素组成的网格,该网格使用屏幕尺寸来确定子元素的宽度以及在一行中放置多少个子元素。

我想要统一的东西:

    所有子项的宽度。应该在所有行中都相同,并且 由“完整”行确定。 “完整”行中的所有边距在子级之间以及外部左侧和右侧都必须一致。 至少是同一行中所有子项的高度(如果某些行比其他行高,则可以,尽管最好的实现确实会使所有行的高度相同)。 文本应在所有子项中垂直居中。

如果未填充,我希望将项目置于最后一行的中心,因此在该行上,如果子项之外的极端边距在左侧和右侧较大,则很好(并且确实是首选)。

我有三个接近的解决方案,但没有一个达到目标。

    这个版本有我想要的一切,除了孩子的宽度。如果您注意到最左边和最右边的边距大于整行上的孩子之间的边距。理想情况下,我希望孩子们伸展得足够长,以便他们在整行上的边距在两侧(组外)和孩子之间都是相同的,然后将相同的宽度应用于最后一行上溢出的孩子(谁能左右边距较大)。

#container
  list-style-type: none !important;
  display: flex;
 flex-flow: row wrap;
 justify-content:center;
 /*style*/
 padding: 0.5em;
 background-color: royalblue;



.child 
  display: flex;
   justify-content: center;
   align-items: center;
   /*style*/
   margin: 0.5em;
   padding: 1em;
 /*  min-height: 80px;*/
   width: 100px;
   background-color: lightblue;
<ul id ="container">
        <li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li>
</ul>
    此版本具有右侧的宽度/边距,但当一个框的行中的文本多于其他框时,文本不会垂直居中。

ul 
  display: flex;
  flex-wrap: wrap;
  justify-content: center;


li 
  min-width: 40px;
  text-align: center;
  flex-grow: 1;
  flex-basis: 100px;
  max-width: 100%;

@media (min-width: 200px) 
  li 
    max-width: 50%;
  

@media (min-width: 300px) 
  li 
    max-width: 33.33333%;
  

@media (min-width: 400px) 
  li 
    max-width: 25%;
  

@media (min-width: 500px) 
  li 
    max-width: 20%;
  

@media (min-width: 600px) 
  li 
    max-width: 16.66667%;
  

@media (min-width: 700px) 
  li 
    max-width: 14.28571%;
  

@media (min-width: 800px) 
  li 
    max-width: 12.5%;
  

@media (min-width: 900px) 
  li 
    max-width: 11.11111%;
  

@media (min-width: 1000px) 
  li 
    max-width: 10%;
  

@media (min-width: 1100px) 
  li 
    max-width: 9.09091%;
  

@media (min-width: 1200px) 
  li 
    max-width: 8.33333%;
  

@media (min-width: 1300px) 
  li 
    max-width: 7.69231%;
  

@media (min-width: 1400px) 
  li 
    max-width: 7.14286%;
  

@media (min-width: 1500px) 
  li 
    max-width: 6.66667%;
  

@media (min-width: 1600px) 
  li 
    max-width: 6.25%;
  

@media (min-width: 1700px) 
  li 
    max-width: 5.88235%;
  

@media (min-width: 1800px) 
  li 
    max-width: 5.55556%;
  

@media (min-width: 1900px) 
  li 
    max-width: 5.26316%;
  

@media (min-width: 2000px) 
  li 
    max-width: 5%;
  

@media (min-width: 2100px) 
  li 
    max-width: 4.7619%;
  


ul, li 
  margin: 0;
  padding: 0;
  list-style: none;


ul 
  background-color: tomato;


li .content 
  margin: 0.5em;
  background-color: darkgreen;

li img 
  width: 100%;
  opacity: 0.5;

li figure, li img 
  margin: 0;
  padding: 0;
    <ul>
      <li>
        <div class="content">
          hi there
        </div>
      </li>
      <li>
        <div class="content">
          hi there
        </div>
      </li>
      <li>
        <div class="content">
          hi there
        </div>
      </li>
      <li>
        <div class="content">
          hi there
        </div>
      </li>
      <li>
        <div class="content">
          hi there
        </div>
      </li>
      <li>
        <div class="content">
          hi there
        </div>
      </li>
      <li>
        <div class="content">
          hi there
        </div>
      </li>
      <li>
        <div class="content">
          hi there
        </div>
      </li>
      <li>
        <div class="content">
          hi there
        </div>
      </li>
      <li>
        <div class="content">
          hi there
        </div>
      </li>
      <li>
        <div class="content">
          hi there
        </div>
      </li>
      <li>
        <div class="content">
          hi there
        </div>
      </li>
      <li>
        <div class="content">
          hi there
        </div>
      </li>
      <li>
        <div class="content">
          hi there
        </div>
      </li>
      <li>
        <div class="content">
          I am taller then the other children on this row        </div>
      </li>
      <li>
        <div class="content">
          hi there
        </div>
      </li>
      <li>
        <div class="content">
          hi there
        </div>
      </li>
</ul>
    这个版本,获得正确的边距和高度,但它不会保持未填充行中子项的宽度与已填充行的子项宽度相同。 这实际上非常重要。我更喜欢第一个版本(侧边距不等),而不是这个。

ul, li 
  border: 1px solid black;

#container
  list-style-type: none !important;
  display: flex;
 flex-flow: row wrap;
 justify-content:center;

 /*style*/
 padding: 0.5em;
 background-color: royalblue;



.child 
  display: flex;
   justify-content: center;
   align-items: center;
   /*style*/
   margin: 0.5em;
   padding: 1em;
   min-height: 80px;
  min-width: 80px;  
  flex-grow: 1;
  /* width: 25%;*/
   background-color: lightblue;
<ul id ="container">
        <li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li><li class ="child"><a href="http://www.google.com"><span class="tf"></span><div class="tf2">Name 1<br>location</div></a></li>

</ul>

【问题讨论】:

基本上......这对于 flexbox 来说是不可能的......这不是它的用途。你真的需要一个网格框架……那不是 flexbox。 对不起,那你在说什么,我必须对所有内容进行硬编码? 你必须承认 flexbox 不是一个网格系统……它只是另一种布局方法。它解决了一些问题……但不是全部。 我可以接受 - 你能给我一个解决方案吗? 当然还有更多的技术可以做到这一点,但您也可以将您的 li 项目设为display: flex; justify-content: center; align-items: center。 jsfiddle 【参考方案1】:

在@michaPau 的帮助下,通过使用 sass,我能够得到我想要的一切。我按照他/她的建议将这段代码添加到我的“版本 2”中,并且可以正常工作。

/* this is the additional code that gets it to work: thanks to @michaPau */

li    
  display: flex
  justify-content: center 
  align-items: center

/*  --- end of michaPau's code --- */

这是带有功能代码的代码笔。您需要点击编译按钮才能从 sass 转换为纯 css: http://codepen.io/ihatecoding/pen/KzyjrE

这是html

<ul>
  <li>
    <div class="content">
      hi there
    </div>
  </li>
  <li>
    <div class="content">
      hi there
    </div>
  </li>
  <li>
    <div class="content">
      hi there
    </div>
  </li>
  <li>
    <div class="content">
      hi there
    </div>
  </li>
  <li>
    <div class="content">
      hi there
    </div>
  </li>
  <li>
    <div class="content">
      hi there
    </div>
  </li>
  <li>
    <div class="content">
      hi there
    </div>
  </li>
  <li>
    <div class="content">
      hi there
    </div>
  </li>
  <li>
    <div class="content">
      hi there
    </div>
  </li>
  <li>
    <div class="content">
      hi there
    </div>
  </li>
  <li>
    <div class="content">
      hi there
    </div>
  </li>
  <li>
    <div class="content">
      hi there
    </div>
  </li>
  <li>
    <div class="content">
      hi there
    </div>
  </li>
  <li>
    <div class="content">
      hi there
    </div>
  </li>
  <li>
    <div class="content">
      I am taller then the other children on this row        </div>
  </li>
  <li>
    <div class="content">
      hi there
    </div>
  </li>
  <li>
    <div class="content">
      hi there
    </div>
  </li>

这是完整的 sass(包括 @michaPau 的修复):

<!-- language: lang-css -->


=flex-wrap-fix($flex-basis, $max-viewport-width)
  flex-grow: 1
  flex-basis: $flex-basis
  max-width: 100%

  $multiplier: 1
  $current-width: 0px

  @while $current-width < $max-viewport-width
    $current-width: $current-width + $flex-basis
    $multiplier: $multiplier + 1

    @media (min-width: $flex-basis * $multiplier)
      max-width: percentage(1 / $multiplier)

ul
  display: flex
  flex-wrap: wrap
  justify-content: center

li
  // I want the width to be between the following two sizes
  min-width: 40px
  text-align: center
  //max-width: 100px
  // this keeps all the elements the same size
  // **as long as they are on the same row**
  // but I want them to all the same width everywhere
  //flex: 1 0 0

  +flex-wrap-fix(100px, 2000px)

// demo styles

ul, li
  margin: 0
  padding: 0
  list-style: none

ul
  background-color: tomato

li  
  .content 
    margin: .5em
    background-color: darkgreen

/* this is the extra new code thanks to @michaPau */

li    
  display: flex
  justify-content: center 
  align-items: center

/*  ---end of michaPau's code --- */

  // the image may have variable width, I want it to take the entire space calculated by flexbox
  img
    width: 100%
    opacity: .5

  figure, img
    margin: 0
    padding: 0

【讨论】:

在类似的情况下让我永远绊倒的一件事是 flex-basis 默认在处理潜在的电网平等中断时具有巨大的影响。这是来自 w3 的 flex-basis 0 vs auto 的视觉描述 我不明白为什么在您提供的flexbox: auto 示例中,具有相同文本(“短”)的两个元素的宽度不同。你能解释一下@systemaddict吗? 我会重申: flex-basis 设置内部弹性框项目的初始大小。如MDN 中所述,默认值为autoflex-basis:auto 处理(本质上)内容不使用的空间。它会考虑内容的大小。这不是问题,因为所有内容的大小都相同 - 可能是单型字符,或者相同大小的图片/div。要完全根据所需的元素比例“自上而下”计算大小,那么您需要使用 flex-basis:0; 现在有意义吗?

以上是关于Flexbox 挑战:如何在整行中使用相同且均匀的边距进行换行的主要内容,如果未能解决你的问题,请参考以下文章

QTableView:如何将鼠标悬停在整行上?

如何使 flexbox 项目的大小相同?

Flexbox 大小均匀的元素,无论内容如何

如何使用 flexbox 均匀地显示内容卡,包括边距边 [重复]

整行的卡片/盒子尺寸相同,具体取决于最大的卡片

如何使用 flexbox 让中间元素始终完美居中 [重复]