How to keep wrapped flex-items the same width as the elements on the previous row?

前端 未结 13 1012
一整个雨季
一整个雨季 2020-11-29 01:24

I have a

    that is a flex-box and a bunch of
  • s in it which are the flex-items.

    I am trying to get the

相关标签:
13条回答
  • 2020-11-29 01:54

    Setting the min-width and max-width as percentages has allowed all images to stay the same width when they break onto the next line. It is not ideal, but closer to what you are after?

    li {
      min-width: 15%;
      max-width: 15%;  
    }

    0 讨论(0)
  • 2020-11-29 01:56

    I came here looking to solve the same problem for a flex box I have. I've since realised that this is now much easier with display: grid as detailed here and here.

    0 讨论(0)
  • 2020-11-29 01:56

    I had the same issue, so I used a very tiny bit of Jquery to control the width of the boxes and make them all the same width even once they wrap.

    My demo is on CodePen Flex wrap, with equal width on new row

    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();
    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:#ffffd;
    }
    
    .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;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <ul class="flex-container wrap">
      <li class="item">1</li>
      <li class="item">2</li>
      <li class="item">3</li>
      <li class="item">4</li>
      <li class="item">5</li>
      <li class="item">6</li>
      <li class="item">7</li>
      <li class="item">8</li>
      <li class="item">9</li>
    </ul>

    0 讨论(0)
  • 2020-11-29 01:57

    use max-width: 40px not max-width: 100px

    0 讨论(0)
  • 2020-11-29 02:06

    if the layout is fixed, you could simply add hidden items and toggle their visibility using css breakpoints for the pixels where wrapping happens.

    for example, in the following scenario .columned-list has 3 .columned-list-item elements, and for the pixels within which the 3rd .columned-list-item element wraps to the next row, I just make the 4th .columned-list-item element .hidden-item - which is normally invisible - visible :

    .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;
                }
    
    
            }
    
    0 讨论(0)
  • 2020-11-29 02:09

    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

    0 讨论(0)
提交回复
热议问题