如何保持包装的flex-items与前一行的元素宽度相同?

时间:2014-04-24 16:13:59

标签: css flexbox

我有一个<ul>,它是一个弹性框和一堆<li>,其中是flex项。

我试图让<li>具有灵活的宽度,使用最小宽度和最大宽度保持两种尺寸。只要它们在同一条线上,它就能很好地工作。但是,当它们换行时,新行上的<li>会尽可能多地使用空间。这意味着它们在第一行很小,而在第二行很少,只有少数几行。

有没有办法告诉flexbox在包装后保持项目的宽度,同时保持灵活的宽度?

包装演示:

enter image description here

我的代码如下所示:

<ul>
  <li>
    <figure>
      <img src="http://placekitten.com/g/250/250">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/100/100">
    </figure>
  </li>
  <!-- ... -->
</ul>

CSS:

ul {
  display: flex;
  flex-wrap: wrap;
}

  li {
    min-width: 40px;
    max-width: 100px;
    flex: 1 0 0;
  }

Here's a live example on codepen with some extra comments ,调整窗口大小以查看它。

13 个答案:

答案 0 :(得分:51)

TL; DR

这不是我称之为解决方案本身,但这是一个相当优雅的解决方法,只使用媒体查询,更重要的是没有JavaScript

Mixin(SCSS):

@mixin flex-wrap-fix($flex-basis, $max-viewport-width: 2000px) {
  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);
    }
  }
}

用法:

将mixin应用于您的弹性项目:

.flex-item {
  @include flex-wrap-fix(100px)
}

更新

只要你的flex容器宽度与你的视口大小相匹配,上面的mixin应该可以解决这个问题,就像OP的例子中的情况一样。否则,媒体查询将无法帮助您,因为它们始终基于视口宽度。但是,您可以使用css-element-queries库及其元素查询而不是浏览器媒体查询。这是一个可以应用于flex 容器的mixin:

@mixin flex-container-wrap-items($flex-basis, $max-expected-width: 2000px) {
  display: flex;
  flex-wrap: wrap;

  > * {
    max-width: 100%;
    flex-grow: 1;
    flex-basis: $flex-basis;
  }

  $multiplier: 1;
  $current-width: 0px;

  @while $current-width < $max-expected-width {
    $current-width: $current-width + $flex-basis;
    $multiplier: $multiplier + 1;

    &[min-width~="#{$flex-basis * $multiplier}"] > * {
      max-width: percentage(1/$multiplier);
    }
  }
}

说明:

让我们说,根据OP的示例,我们希望每个项目的最大宽度为100px,因此我们知道,对于浏览器宽度100px,我们可以在每行中放置一个项目,等等:

| Viewport Width | Max Item Count Per Row | Item Width (min-max) |
|----------------|------------------------|----------------------|
| <= 100         | 1                      | 0px - 100px          |
| <= 200         | 2                      | 50px - 100px         |
| <= 300         | 3                      | 50px - 100px         |
| <= 400         | 4                      | 50px - 100px         |
| <= 500         | 5                      | 50px - 100px         |
| <= 600         | 6                      | 50px - 100px         |

我们可以编写媒体查询来创建以下规则:

| Viewport Width | Max Item Count Per Row | Item Max Width | Calculation |
|------------------------------------------------------------------------|
| <= 100px       | 1                      | 100%           | (100/1)     |
| <= 200px       | 2                      | 50%            | (100/2)     |
| <= 300px       | 3                      | 33.33333%      | (100/3)     |
| <= 400px       | 4                      | 25%            | (100/4)     |
| <= 500px       | 5                      | 20%            | (100/5)     |
| <= 600px       | 6                      | 16.66666%      | (100/6)     |

像这样:

li {
  flex: 1 0 0
  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.66666%; }
}

当然,这是重复的,但很可能你正在使用某种预处理器,它可以为你处理重复性。这正是上面 TL; DR 部分中的mixin所做的。

我们现在要做的就是将100px指定为flex-basis可选创建最大浏览器窗口宽度(默认为2000px)媒体查询:

@include flex-wrap-fix(100px)

实施例

最后,使用上面的mixin,使用所需输出的原始CodePen示例的分叉版本:

http://codepen.io/anon/pen/aNVzoJ

demo of the solution

答案 1 :(得分:9)

我一直在尝试使用您的codepen并设置 flex: 0 1 10%

当然你可以设置任何你想要的弹性基础,我只想证明一点,如果你设置弹性基础并允许它缩小,在这种情况下它会表现得更好。

我认为这就是你所需要的。这是预览: http://codepen.io/anon/pen/bwqNEZ

干杯

答案 2 :(得分:2)

I think I got it...but it's hacky. The result is the 14 images each scaling from 100px wide down to 40px, even on multiple rows.

From 107px to 40px Width

  • Added a duplicate set of the 14 original <li>s and added them to the flex <ul>.
  • Next, the second set was rendered invisible:

    li:nth-of-type(n + 15) {
      visibility: hidden;
    }
    
  • In order to maintain uniform flexibility the following changes to each <li>:

    li {
      min-width: 40px;
      max-width: 10%;
      flex: 1 0 100px;
    }
    

Please review the CodePen

and/or the Snippet in Full Page mode.

ul {
  display: flex;
  flex-wrap: wrap;
  max-height: 258px;
}
li {
  min-width: 40px;
  max-width: 10%;
  flex: 1 0 100px;
}
ul,
li {
  margin: 0;
  padding: 0;
  list-style: none;
}
ul {
  background-color: tomato;
}
li {
  margin: 0.5em;
  background-color: darkgreen;
}
li img {
  width: 100%;
  opacity: 0.5;
}
li figure,
li img {
  margin: 0;
  padding: 0;
}
li:nth-of-type(n + 15) {
  visibility: hidden;
}
<ul>
  <li>
    <figure>
      <img src="http://placekitten.com/g/250/250">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/101/101">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/201/201">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/150/150">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/80/80">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/111/111">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/40/40">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/110/110">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/75/75">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/89/89">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/150/150">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/32/32">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/61/61">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/320/320">
    </figure>
  </li>



  <li>
    <figure>
      <img src="http://placekitten.com/g/250/250">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/101/101">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/201/201">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/150/150">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/80/80">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/111/111">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/40/40">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/110/110">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/75/75">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/89/89">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/150/150">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/32/32">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/61/61">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/320/320">
    </figure>
  </li>
</ul>

答案 3 :(得分:2)

我来这里的目的是为我拥有的弹性盒解决相同的问题。从那以后,我意识到使用display: grid(如详细的herehere)现在更容易了。

答案 4 :(得分:1)

它不能很好地工作,但是你可以通过列来实现这个方向。

column-gap: 10px;
column-width: 150px;

https://codepen.io/hobbeshunter/pen/OgByNX

答案 5 :(得分:1)

min-widthmax-width设置为百分比可以让所有图像在进入下一行时保持相同的宽度。这不是理想的,但更接近你的目标?

&#13;
&#13;
li {
  min-width: 15%;
  max-width: 15%;  
}
&#13;
&#13;
&#13;

答案 6 :(得分:0)

这不是完美的,但值得一试。 http://codepen.io/anon/pen/MKmXpV

更改

li
  width: 7.1428%
  flex: 0 0 auto

figure
  margin: 0 auto
  background-color: darkgreen
  min-width: 40px
  max-width: 100px
  • 将li flex更改为&#34; 0 0 auto&#34;并且li宽度基于的百分比 lis的数量。
  • 将最小和最大宽度从li移动到图中
  • 将绿色背景移动到图中并将数字居中 lis

答案 7 :(得分:0)

我的解决方案并不理想,因为它倾向于JQuery:http://codepen.io/BigWillie/pen/WwyEXX

CSS

ul {
  display: flex;
  flex-wrap: wrap;
}

li {
  min-width: 40px;
  max-width: 100px;
  flex: 1;
}

的JavaScript

var eqRowFlexItem = function(elem) {
    var w;
    var $elem = $(elem);
    // Clear out max-width on elements
    $elem.css('max-width', '');
    w = $(elem).eq(0).width();
    $(elem).css('max-width', w);
}

eqRowFlexItem('li');

$(window).resize(function() {
    eqRowFlexItem('li');
});

我不完全确定它是否能解决问题。我找到了这篇文章,标题与我遇到的问题相符。我在一个效果之后,我会在更大的屏幕上每行有更多的元素 - 在较小的屏幕上每行的元素更少。在这两种情况下,这些元素也需要扩展以适应......跨设备。

但是,最后一行的那些杂散元素将始终展开以填充剩余空间。

JQuery获取第一个元素的宽度 - 并将其作为最大宽度应用于每个元素。 OP希望块落在最小宽度/最大宽度范围内。在CSS中设置max-width似乎有效。我们清除元素的最大宽度,因此默认为CSS中的最大宽度...然后获取实际宽度。

答案 8 :(得分:0)

我遇到了同样的问题,所以我使用了一小部分Jquery来控制盒子的宽度,即使它们包裹也会使它们的宽度相同。

我的演示在CodePen Flex wrap, with equal width on new row

&#13;
&#13;
chart1.Legends.Add(seriesName);
chart1.Legends[0].Docking = Docking.Bottom;
chart1.Legends[0].TableStyle = LegendTableStyle.Wide;
chart1.Legends[0].BorderColor = Color.CornflowerBlue;
chart1.Legends[0].BorderDashStyle = ChartDashStyle.Dash;
chart1.Legends[0].BorderWidth = 1;
&#13;
function resize(){
  var colWidth;
  var screen = $(window).width(); 
  
  if(screen < 576){
    colWidth = Math.round(screen / 2) - 31;
    $(".item").width(colWidth);
  } 
  if(screen > 575 && screen < 768){
    colWidth = Math.round(screen / 3) - 31;
    $(".item").width(colWidth);
  } 
  else if (screen > 767 && screen < 992){
      colWidth = Math.round(screen / 4) -31;
      $(".item").width(colWidth);
  }
  else if (screen > 991 ){
      colWidth = Math.round(screen / 6) -31;
      $(".item").width(colWidth);
  }
}
  
window.onresize = function() {
  resize();
}

resize();
&#13;
html,
body{
  padding:0;
  margin:0;
}
.flex-container {
  padding: 0;
  margin: 0;
  list-style: none;
  -ms-box-orient: horizontal;
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -moz-flex;
  display: -webkit-flex;
  display: flex;
  justify-content: left;
  background-color:#ddd;
}

.wrap    { 
  -webkit-flex-wrap: wrap;
  flex-wrap: wrap;
}  

.item {
  background: tomato;
  height: 100px;
  margin:0 15px;
  line-height: 100px;
  color: white;
  font-weight: bold;
  font-size: 2em;
  text-align: center;
  margin-top:10px;
}
&#13;
&#13;
&#13;

答案 9 :(得分:0)

对于Stylus,您可以使用以下混合:https://codepen.io/anon/pen/Epjwjq


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

     $multiplier = ceil($max / $basis)

     for i in (1..$multiplier) {
       @media(min-width: ($basis * i)) {
         max-width: percentage(1/i)
       }
     }
   }

答案 10 :(得分:0)

如果布局是固定的,则可以简单地添加隐藏的项目,并使用css断点为发生换行的像素切换可见性。

例如,在以下情况下, .columned-list 具有3个 .columned-list-item 元素,并且对于其中第三个.columned-list的像素-item元素环绕到下一行,我只是将第四个 .columned-list-item 元素 .hidden-item -通常是不可见的-可见:

.columned-list {
            display: flex;
            flex-wrap: wrap;
            margin-left: 35px;


            justify-content: flex-start;



            .hidden-item {
                display: none !important;

                @media only screen and (max-width: 1375px) {
                    flex: 1 0 auto !important;
                    min-width: 410px !important;
                    width: 30% !important;
                    margin: 0 37px 37px 0 !important;
                    max-width: 100% !important;
                    display: flex !important;
                    background-color: #fff !important;
                }

                @media only screen and (max-width: 928px) {
                    display: none !important;
                }
            }

            .columned-list-item {
                flex: 1 0 auto;
                min-width: 410px;
                min-height: 1px !important; // <3 IE.
                width: 30%;
                margin: 0 37px 37px 0;
                max-width: 100%;
                display: flex;
                flex-direction: column;
                align-items: center;
                color: #676562;
                background-color: #f2f3f5;

                a:nth-of-type(1) {
                    position: relative;
                    min-height: 84px;
                    width: 100%;

                    img {
                        width: 100%;
                        height: auto;
                    }

                    div {
                        min-height: 88px;
                        max-width: 203px;
                        padding: 0 15px;
                        top: 50%;
                        transform: translateY(-50%);
                        position: absolute;
                        display: flex;
                        justify-content: center;
                        align-items: center;

                        background-color: #fff;
                        opacity: 0.6;
                        span {
                            height: 55px;
                            font-family: 'Trade Gothic Next LT W04 Rg', sans-serif;
                            font-size: 28px;
                            font-weight: bold;
                            font-stretch: normal;
                            font-style: normal;
                            line-height: 1;
                            letter-spacing: 0.7px;
                            text-align: left;
                            color: #676562;
                        }

                    }

                }

                a:nth-of-type(2) {

                    padding: 10px 35px;
                    display: flex;
                    flex-direction: column;
                    min-height: 161px;
                    max-width: 390px;

                    strong {
                        font-family: 'Trade Gothic Next LT W04 Bold', sans-serif;
                        font-weight: bold;
                        text-align: center;
                    }
                    span {

                        font-family: 'Trade Gothic Next LT W04 Light', sans-serif;
                        font-size: 15px;
                        font-weight: normal;
                        font-stretch: normal;
                        font-style: normal;
                        line-height: 1.4;
                        letter-spacing: normal;
                        text-align: center;
                        color: #676562;

                    }
                }

                .buttons-block {
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    width: 298px;
                    max-width: 100%;
                    margin: 10px 0 23px 0;

                    .button-a {
                        width: 114px;
                        height: 22px;
                        min-height: 1px;
                        box-shadow: 0px 1px 0 0 rgba(0, 0, 0, 0.16);
                        background-color: #f28d4e;
                        display: flex;
                        justify-content: center;
                        align-items: center;

                        span {
                            font-family: 'Trade Gothic Next LT W04 Rg', sans-serif;
                            font-size: 15px;
                            font-weight: bold;
                            font-stretch: normal;
                            font-style: normal;
                            line-height: 1.4;
                            letter-spacing: normal;
                            text-align: center;
                            color: #ffffff;
                        }
                    }

                    .button-b {
                        margin-bottom: 0;
                        padding: 0;
                    }

                }

                @media only screen and (max-width: 760px) {
                    margin: 0 0 20px 0;
                }
                @media only screen and (max-width: 410px) {

                    min-width: auto;
                    width: 100%;
                }
            }

            @media only screen and (max-width: 760px) {
                display: flex !important;
                flex-direction: column;
                align-items: center;
                margin-left: 0;
                padding-top: 10px;
            }


        }

答案 11 :(得分:0)

替代-网格

它不是您想要的答案,但是很好用:

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

https://codepen.io/omergal/pen/povzJrz

ul {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(70px, 1fr));
}

li {
  min-width: 40px;
  max-width: 100px;
}

ul,
li {
  margin: 0;
  padding: 0;
  list-style: none;
}
ul {
  background-color: tomato;
}

li {
  margin: 0.5em;
  background-color: darkgreen;
}

img {
  width: 100%;
  opacity: 0.5;
}
figure,
img {
  margin: 0;
  padding: 0;
}
<ul>
      <li>
        <figure>
          <img src="http://placekitten.com/g/250/250">
        </figure>
      </li>
      <li>
        <figure>
          <img src="http://placekitten.com/g/101/101">
        </figure>
      </li>
      <li>
        <figure>
          <img src="http://placekitten.com/g/201/201">
        </figure>
      </li>
      <li>
        <figure>
          <img src="http://placekitten.com/g/150/150">
        </figure>
      </li>
      <li>
        <figure>
          <img src="http://placekitten.com/g/80/80">
        </figure>
      </li>
      <li>
        <figure>
          <img src="http://placekitten.com/g/111/111">
        </figure>
      </li>
      <li>
        <figure>
          <img src="http://placekitten.com/g/40/40">
        </figure>
      </li>
      <li>
        <figure>
          <img src="http://placekitten.com/g/110/110">
        </figure>
      </li>
      <li>
        <figure>
          <img src="http://placekitten.com/g/75/75">
        </figure>
      </li>
      <li>
        <figure>
          <img src="http://placekitten.com/g/89/89">
        </figure>
      </li>
      <li>
        <figure>
          <img src="http://placekitten.com/g/150/150">
        </figure>
      </li>
      <li>
        <figure>
          <img src="http://placekitten.com/g/32/32">
        </figure>
      </li>
      <li>
        <figure>
          <img src="http://placekitten.com/g/61/61">
        </figure>
      </li>
      <li>
        <figure>
          <img src="http://placekitten.com/g/320/320">
        </figure>
      </li>
    </ul>

答案 12 :(得分:-1)

使用max-width: 40px而不是max-width: 100px