Html 当flexbox项目以列模式包装时,容器不会增加其宽度

Html 当flexbox项目以列模式包装时,容器不会增加其宽度,html,css,flexbox,Html,Css,Flexbox,我正在处理嵌套的flexbox布局,其工作原理如下: 最外层(ul#main)是一个水平列表,当添加更多项目时,该列表必须向右扩展。如果它太大,应该有一个水平滚动条 #main { display: flex; flex-direction: row; flex-wrap: nowrap; overflow-x: auto; /* ...and more... */ } 此列表的每个项目(ul#main>li)都有一个标题(ul#main>li>h2)和

我正在处理嵌套的flexbox布局,其工作原理如下:

最外层(
ul#main
)是一个水平列表,当添加更多项目时,该列表必须向右扩展。如果它太大,应该有一个水平滚动条

#main {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    overflow-x: auto;
    /* ...and more... */
}
此列表的每个项目(
ul#main>li
)都有一个标题(
ul#main>li>h2
)和一个内部列表(
ul#main>li>ul.tasks
)。这个内部列表是垂直的,需要时应该包装成列。当包装到更多列中时,其宽度应增加,以便为更多项目腾出空间。此宽度增加也应适用于外部列表的包含项

.tasks {
    flex-direction: column;
    flex-wrap: wrap;
    /* ...and more... */
}
我的问题是,当窗口的高度变得太小时,内部列表不会换行。我尝试了很多篡改所有flex属性的方法,试图仔细地遵循指南,但没有成功

这显示了我到目前为止的情况

预期结果(我想要的):

实际结果(我得到的):

更老的结果(我在2015年得到的):

更新 经过一些调查,这似乎开始成为一个更大的问题所有主要浏览器的行为方式都相同,这与我的flexbox设计嵌套无关。更简单的flexbox列布局在项目换行时拒绝增加列表的宽度

这清楚地说明了问题所在。在当前版本的Chrome、Firefox和IE11中,所有项目都正确包装;列表的高度在
模式下增加,但其宽度在
模式下不增加。此外,在更改
列的高度时,元素根本不会立即回流,但在
模式下,元素会立即回流

然而,事实似乎表明我想做的应该是可能的

有人能想出解决这个问题的办法吗

更新2 在使用JavaScript在调整大小事件期间更新各种元素的高度和宽度进行了大量实验之后,我得出了这样的结论:用这种方法解决这个问题太复杂,太麻烦了。此外,添加JavaScript肯定会破坏flexbox模型,它应该尽可能保持干净

现在,我回到
overflow-y:auto
而不是
flex-wrap:wrap
,这样内部容器在需要时可以垂直滚动。这并不漂亮,但这是一种前进的方式,至少不会太多地破坏可用性。

问题 这似乎是flex布局中的一个根本缺陷

列方向上的flex容器不会扩展以容纳其他列。(这在
弹性方向:行
中不是问题)

这个问题已经被问了很多次(见下面的列表),在CSS中没有明确的答案

很难将其确定为bug,因为该问题在所有主要浏览器中都会出现。但它确实提出了一个问题:

为什么所有主流浏览器都使用flex容器 在换行时按行方向展开,但不按列方向展开

你会认为他们中至少有一个会做对。我只能推测原因。也许这是一个技术上困难的实现,并被搁置在本次迭代中

更新:该问题似乎已在Edge v16中得到解决


问题的说明 OP制作了一个有用的演示来说明这个问题。我在这里复制它:


解决方案选项 来自Stack Overflow社区的黑客解决方案:


更多分析

描述相同问题的其他帖子
问题 这似乎是flex布局中的一个根本缺陷

列方向上的flex容器不会扩展以容纳其他列。(这在
弹性方向:行
中不是问题)

这个问题已经被问了很多次(见下面的列表),在CSS中没有明确的答案

很难将其确定为bug,因为该问题在所有主要浏览器中都会出现。但它确实提出了一个问题:

为什么所有主流浏览器都使用flex容器 在换行时按行方向展开,但不按列方向展开

你会认为他们中至少有一个会做对。我只能推测原因。也许这是一个技术上困难的实现,并被搁置在本次迭代中

更新:该问题似乎已在Edge v16中得到解决


问题的说明 OP制作了一个有用的演示来说明这个问题。我在这里复制它:


解决方案选项 来自Stack Overflow社区的黑客解决方案:


更多分析

描述相同问题的其他帖子
    • 可能的JS解决方案

      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");
           }
      }
      
      可能的JS解决方案

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

      由于还没有提出解决方案或适当的解决方法,我设法用一种稍微不同的方法获得了请求的行为。我没有将布局分成3个不同的div,而是将所有项目添加到1个div中,并在其中添加一些div来创建分隔

      建议的解决方案是硬编码的,假设我们有3个部分,但可以扩展到通用部分。主要的想法是
          element.style.flexBasis = "auto";
          element.style.flexBasis = `${element.scrollWidth}px`;
      
        _ensureWidth(parentElement) {
      let totalRealWidth = 0;
      let parentElementBoundingRect  = parentElement.getBoundingClientRect()
      let lowestLeft = parentElementBoundingRect.x;
      let highestRight = parentElementBoundingRect.width;
      for (let i = 0; i < parentElement.children.length; i++) {
        let { x, width } = parentElement.children[i].getBoundingClientRect();
        if (x < lowestLeft) {
          lowestLeft = x;
        }
        if (x + width > highestRight) {
          highestRight = x + width;
        }
      }
      totalRealWidth = highestRight - lowestLeft;
      parentElement.style.width = `${totalRealWidth}px`;