如何保持包裹的 flex-items 与前一行元素的宽度相同? [英] How to keep wrapped flex-items the same width as the elements on the previous row?

查看:25
本文介绍了如何保持包裹的 flex-items 与前一行元素的宽度相同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个

    ,它是一个 flex-box 和一堆
  • ,它们是 flex-items.>

    我试图让

  • 具有灵活的宽度,使用 min-width 和 max-width 保持在两个大小之间.只要它们在同一条线上,它就可以很好地工作.但是,当它们换行时,新行上的
  • 会尽可能多地使用空间.这意味着它们在第一行中很小,而当它们很少时,它们在第二行中很大.

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

    包装演示:

    我的代码如下:

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

    和 CSS:

    ul {显示:弹性;flex-wrap: 包裹;}李{最小宽度:40px;最大宽度:100px;弹性:1 0 0;}

    I have a <ul> that is a flex-box and a bunch of <li>s in it which are the flex-items.

    I am trying to get the <li> to have a flexible width, that stays between two sizes using min-width and max-width. It works great as long as they are on the same line. However, when they wrap, the <li> s on the new line use as much space as they can. Which means they are small on the first line, and big on the second line when there are just a few of them.

    Is there a way to tell flexbox to keep the items the width after wrapping, while keeping the flexible width?

    wrapping demo:

    My code looks like this:

    <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>
    

    And the 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, resize your window to see it wrap.

    解决方案

    TL;DR

    This is not something I'd call a solution per se, but it's a rather elegant workaround that only uses media queries, and more importantly no 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);
        }
      }
    }
    

    Usage:

    Apply the mixin to your flex item:

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

    Update:

    The above mixin should do the trick, as long as you your flex container width matches your viewport size, as is the case in OP's example. Media queries won't help you otherwise, because they're always based on the viewport width. However, you could use the css-element-queries library and its element queries instead of browser media queries. Here's a mixin that you can apply to the flex container:

    @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);
        }
      }
    }
    


    Explanation:

    Let's say, as per the OP's example, we want each item to have a maximum width of 100px, so we know that for a browser width of 100px we can fit one item per row, and so on:

    | 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         |
    

    We can write media queries to create the following rules:

    | 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)     |
    

    Like this:

    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%; }
    }
    

    Of course, that's repetitive, but most likely you're using some sort of preprocessor, which can take care of the repetitiveness for you. That's precisely what the mixin in the above TL;DR section does.

    All we have to do now is to specify 100px as our flex-basis, and optionally the maximum browser window width (defaults to 2000px) to create the media queries for:

    @include flex-wrap-fix(100px)
    

    Example

    Finally, a forked version of the original CodePen example with the desired output, using the above mixin:

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

    这篇关于如何保持包裹的 flex-items 与前一行元素的宽度相同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆