我正在做一个嵌套的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属性,试图一丝不差地遵循CSS-Tricks的指导方针,但运气不太好。

这个JSFiddle显示了我目前所拥有的。

预期结果(我想要的):

实际结果(我得到的):

以前的结果(我2015年的结果):

更新

经过一些调查,这开始看起来是一个更大的问题。所有主流浏览器的行为方式都是一样的,这与我的flexbox设计嵌套无关。即使是更简单的flexbox列布局也拒绝在项目换行时增加列表的宽度。

另一个JSFiddle清楚地说明了这个问题。在当前版本的Chrome、Firefox和IE11中,所有项目都能正确换行;列表的高度在行模式下增加,但其宽度在列模式下不增加。同样,在改变列模式的高度时,根本没有元素的立即回流,但行模式中有。

然而,官方规格(具体看例5)似乎表明我想做的事情应该是可能的。

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

更新2

在多次尝试使用JavaScript在调整大小事件期间更新各种元素的高度和宽度后,我得出的结论是,尝试以这种方式解决它太复杂,太麻烦了。此外,添加JavaScript肯定会破坏flexbox模型,它应该尽可能保持干净。

现在,我回到了overflow-y: auto,而不是flex-wrap: wrap,以便内部容器在需要时垂直滚动。它并不漂亮,但至少是一种不太破坏可用性的方法。


当前回答

CSS-only解决方案

在这个问题提出近6年后,这个flexbox漏洞仍然存在,所以这里有一个css只适用于flex direction:列的解决方案,以解决其他任何最终出现在这里的问题:

body { background-color: grey; } button { background-color: white; border: none; border-radius: 4px; width: 80px; height: 40px; margin: 4px; } /* WORKAROUND FOR flex-direction: column WITH WRAP IS BELOW */ .wrapped-columns { flex-direction: row; flex-wrap: wrap; writing-mode: vertical-lr; text-orientation: upright; } /* Ensures content is rendered correctly in Firefox */ .wrapped-columns * { writing-mode: horizontal-tb; } <div class="wrapped-columns"> <button>Button 1</button> <button>Button 2</button> <button>Button 3</button> <button>Button 4</button> <button>Button 5</button> <button>Button 6</button> <button>Button 7</button> <button>Button 8</button> <button>Button 9</button> <button>Button 10</button> <button>Button 11</button> <button>Button 12</button> <button>Button 13</button> <button>Button 14</button> </div>

此解决方案提供了与flex-direction: column相同的结果,并且适用于flex-wrap: wrap和wrap-reverse。

其他回答

处理:

使用javascript在元素加载到屏幕上后手动设置包装器的宽度并不难。宽度始终是最后一个子元素的右手点。

在react中,我根据添加到flex包装器的任何子包装器的布局更改更新了它,但这可以在任何时候调用,你添加或删除子包装器。

let r = refWrapper.current.lastElementChild.getBoundingClientRect()
refWrapper.current.style.width = (r.x+r.width )+'px'

`

哪里refWrapper是你的你的flex元素

这个问题

这看起来像是flex布局的一个基本缺陷。

列方向的伸缩容器不会扩展以容纳其他列。(这在flex-direction: row中不是问题。)

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

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

怎么可能所有主流浏览器都有flex容器呢 按行方向展开而不是按列方向展开?

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

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


问题说明

OP创建了一个有用的演示来说明这个问题。我复制到这里:http://jsfiddle.net/nwccdwLw/1/


方法选择

来自Stack Overflow社区的hack解决方案:

“看起来这个问题仅靠CSS无法解决,所以我建议您使用JQuery解决方案。” 奇怪的是,大多数浏览器都没有正确地实现列伸缩容器,但对写入模式的支持相当不错。因此,您可以使用具有垂直写入模式的行伸缩容器。”


更多的分析

铬Bug报告 Mark Amery的回答是


其他描述同样问题的帖子

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>? https://stackoverflow.com/q/55709208/3597276 Flexbox wrap not increasing the width of parent? Absolute Flex container not changing to the correct width with defined max-height

不幸的是,这么多的主流浏览器在多年后都受到这个错误的困扰。考虑一个Javascript解决方案。每当浏览器窗口调整大小,或者向元素添加内容时,执行这段代码使其调整为适当的宽度。你可以在框架中定义一个指令来为你做这件事。

    element.style.flexBasis = "auto";
    element.style.flexBasis = `${element.scrollWidth}px`;

CSS-only解决方案

在这个问题提出近6年后,这个flexbox漏洞仍然存在,所以这里有一个css只适用于flex direction:列的解决方案,以解决其他任何最终出现在这里的问题:

body { background-color: grey; } button { background-color: white; border: none; border-radius: 4px; width: 80px; height: 40px; margin: 4px; } /* WORKAROUND FOR flex-direction: column WITH WRAP IS BELOW */ .wrapped-columns { flex-direction: row; flex-wrap: wrap; writing-mode: vertical-lr; text-orientation: upright; } /* Ensures content is rendered correctly in Firefox */ .wrapped-columns * { writing-mode: horizontal-tb; } <div class="wrapped-columns"> <button>Button 1</button> <button>Button 2</button> <button>Button 3</button> <button>Button 4</button> <button>Button 5</button> <button>Button 6</button> <button>Button 7</button> <button>Button 8</button> <button>Button 9</button> <button>Button 10</button> <button>Button 11</button> <button>Button 12</button> <button>Button 13</button> <button>Button 14</button> </div>

此解决方案提供了与flex-direction: column相同的结果,并且适用于flex-wrap: wrap和wrap-reverse。

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