When flexbox items wrap in column mode, container does not grow its width

后端 未结 6 1963
长情又很酷
长情又很酷 2020-11-21 05:22

I am working on a nested flexbox layout which should work as follows:

The outermost level (ul#main) is a horizontal list that must expand to the right w

相关标签:
6条回答
  • 2020-11-21 06:06

    Possible JS solution..

    var ul = $("ul.ul-to-fix");
    
    if(ul.find("li").length>{max_possible_rows)){
        if(!ul.hasClass("width-calculated")){
            ul.width(ul.find("li").eq(0).width()*ul.css("columns"));
            ul.addClass("width-calculated");
         }
    }
    
    0 讨论(0)
  • 2020-11-21 06:07

    I just found a really awesome PURE CSS workaround here.

    https://jsfiddle.net/gcob492x/3/

    The tricky: set writing-mode: vertical-lr in the list div then writing-mode: horizontal-tb in the list item. I had to tweak the styles in the JSFiddle (remove a lot of the alignment styles, which aren't necessary for the solution).

    Note: the comment says it only works in Chromium-based browsers, and not Firefox. I've only personally tested in Chrome. It's possible either there's a way to modify this to make it work in other browsers or there have been updates to said browsers that make this work.

    Big shoutout to this comment: When flexbox items wrap in column mode, container does not grow its width. Digging through that issue thread led me to https://bugs.chromium.org/p/chromium/issues/detail?id=507397#c39 which led me to this JSFiddle.

    0 讨论(0)
  • 2020-11-21 06:11

    Since no solution or proper workaround was suggested yet, I managed to obtain the requested behavior with a little different approach. Instead of separating the layout into 3 different divs, I'm adding all the items into 1 div and creating the separation with some more divs in between.

    The proposed solution is hard coded, assuming we have 3 sections, but can be extended to a generic one. The main idea is to explain how we can achieve this layout.

    1. Adding all the items into 1 container div that uses flex to wrap the items
    2. The first item of each "inner container" (I'll call it a section) will have a class, which helps us to do some manipulations that create the separation and styling of each section.
    3. Using :before on each first item, we can locate the title of each section.
    4. Using space creates the gap between the sections
    5. Since the space won't cover the full height of the section I'm also adding :after to the sections so positioning it with absolute position and white background.
    6. To style the background color of each section I'm adding another div inside the first item of each section. I will be position with absolute as well and will have z-index: -1.
    7. To get the correct width of each background, I'm using JS, setting the correct width, and also adding a listener to resize.

    function calcWidth() {
      var size = $(document).width();
      var end = $(".end").offset().left;
    
      var todoWidth = $(".doing-first").offset().left;
      $(".bg-todo").css("width", todoWidth);
    
      var doingWidth = $(".done-first").offset().left - todoWidth;
      $(".bg-doing").css("width", doingWidth);
    
      var doneWidth = $(".end").offset().left - $(".done-first").offset().left;
      $(".bg-done").css("width", doneWidth + 20);
    
    }
    
    calcWidth();
    
    $(window).resize(function() {
      calcWidth();
    });
    .container {
      display: flex;
      flex-wrap: wrap;
      flex-direction: column;
      height: 120px;
      align-content: flex-start;
      padding-top: 30px;
      overflow-x: auto;
      overflow-y: hidden;
    }
    
    .item {
      width: 200px;
      background-color: #e5e5e5;
      border-radius: 5px;
      height: 20px;
      margin: 5px;
      position: relative;
      box-shadow: 1px 1px 5px 0px rgba(0, 0, 0, 0.75);
      padding: 5px;
    }
    
    .space {
      height: 150px;
      width: 10px;
      background-color: #fff;
      margin: 10px;
    }
    
    .todo-first:before {
      position: absolute;
      top: -30px;
      height: 30px;
      content: "To Do (2)";
      font-weight: bold;
    }
    
    .doing-first:before {
      position: absolute;
      top: -30px;
      height: 30px;
      content: "Doing (5)";
      font-weight: bold;
    }
    
    .doing-first:after,
    .done-first:after {
      position: absolute;
      top: -35px;
      left: -25px;
      width: 10px;
      height: 180px;
      z-index: 10;
      background-color: #fff;
      content: "";
    }
    
    .done-first:before {
      position: absolute;
      top: -30px;
      height: 30px;
      content: "Done (3)";
      font-weight: bold;
    }
    
    .bg-todo {
      position: absolute;
      background-color: #FFEFD3;
      width: 100vw;
      height: 150px;
      top: -30px;
      left: -10px;
      z-index: -1;
    }
    
    .bg-doing {
      position: absolute;
      background-color: #EFDCFF;
      width: 100vw;
      height: 150px;
      top: -30px;
      left: -15px;
      z-index: -1;
    }
    
    .bg-done {
      position: absolute;
      background-color: #DCFFEE;
      width: 10vw;
      height: 150px;
      top: -30px;
      left: -15px;
      z-index: -1;
    }
    
    .end {
      height: 150px;
      width: 10px;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div class="container">
    
      <div class="item todo-first">
        <div class="bg-todo"></div>
        Drink coffee
      </div>
      <div class="item">Go to work</div>
    
      <div class="space"></div>
    
      <div class="item doing-first">
        <div class="bg-doing"></div>
        1
      </div>
      <div class="item">2</div>
      <div class="item">3</div>
      <div class="item">4</div>
      <div class="item">5</div>
    
      <div class="space"></div>
    
      <div class="item done-first">
        <div class="bg-done"></div>
        1
      </div>
      <div class="item">2</div>
      <div class="item">3</div>
    
      <div class="end"></div>
    
    </div>

    0 讨论(0)
  • 2020-11-21 06:12

    It is unfortunate that so many major browsers suffer from this bug after many years. Consider a Javascript workaround. Whenever the browser window resizes, or content is added to the element, execute this code to get it to resize to the proper width. You can define a directive in your framework to do it for you.

        element.style.flexBasis = "auto";
        element.style.flexBasis = `${element.scrollWidth}px`;
    
    0 讨论(0)
  • 2020-11-21 06:14

    The Problem

    This looks like a fundamental deficiency in flex layout.

    A flex container in column-direction will not expand to accommodate additional columns. (This is not a problem in flex-direction: row.)

    This question has been asked many times (see list below), with no clean answers in CSS.

    It's hard to pin this as a bug because the problem occurs across all major browsers. But it does raise the question:

    How is it possible that all major browsers got the flex container to expand on wrap in row-direction but not in column-direction?

    You would think at least one of them would get it right. I can only speculate on the reason. Maybe it was a technically difficult implementation and was shelved for this iteration.

    UPDATE: The issue appears to be resolved in Edge v16.


    Illustration of the Problem

    The OP created a useful demo illustrating the problem. I'm copying it here: http://jsfiddle.net/nwccdwLw/1/


    Workaround Options

    Hacky solutions from the Stack Overflow community:

    • "It seems this issue cannot be solved only with CSS, so I propose you a JQuery solution."

    • "It's curious that most browsers haven't implemented column flex containers correctly, but the support for writing modes is reasonably good. Therefore, you can use a row flex container with a vertical writing mode."


    More Analysis

    • Chromium Bug Report

    • Mark Amery's answer


    Other Posts Describing the Same Problem

    • Flex box container width doesn't grow
    • How can I make a display:flex container expand horizontally with its wrapped contents?
    • Flex-flow: column wrap. How to set container's width equal to content?
    • Flexbox flex-flow column wrap bugs in chrome?
    • How do I use "flex-flow: column wrap"?
    • Flex container doesn't expand when contents wrap in a column
    • flex-flow: column wrap, in a flex box causing overflow of parent container
    • Html flexbox container does not expand over wrapped children
    • Flexbox container and overflowing flex children?
    • How can I make a flexbox container that stretches to fit wrapped items?
    • Flex container calculating one column, when there are multiple columns
    • Make container full width with flex
    • Flexbox container resize possible?
    • Flex-Wrap Inside Flex-Grow
    • Flexbox grow to contain
    • Expand flexbox element to its contents?
    • flexbox column stretch to fit content
    • https://stackoverflow.com/q/48406237/3597276
    • flex-flow: column wrap doesn't stretch the parent element's width
    • Why doesn't my <ul> expand width to cover all the <li>?
    • How to have width adjust when flexbox columns wrap?
    • Flexbox wrap not increasing the width of parent?
    0 讨论(0)
  • 2020-11-21 06:14

    Late to the party, but was still running into this issue YEARS later. Ended up finding a solution using grid. On the container you can use

    display: grid;
    grid-auto-flow: column;
    grid-template-rows: repeat(6, auto);
    

    I have an example on CodePen that toggles between the flexbox issue and the grid fix: https://codepen.io/MandeeD/pen/JVLdLd

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