Html 当 flexbox 项目以列模式换行时,容器不会增加其宽度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33891709/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When flexbox items wrap in column mode, container does not grow its width
提问by Anders Tornblad
I am working on a nested flexbox layout which should work as follows:
我正在处理嵌套的 flexbox 布局,它应该按如下方式工作:
The outermost level (ul#main
) is a horizontal list that must expand to the right when more items are added to it. If it grows too big, there should be a horizontal scroll bar.
最外层 ( ul#main
) 是一个水平列表,当添加更多项目时,它必须向右扩展。如果它变得太大,应该有一个水平滚动条。
#main {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
overflow-x: auto;
/* ...and more... */
}
Each item of this list (ul#main?>?li
) has a header (ul#main?>?li?>?h2
) and an inner list (ul#main?>?li >?ul.tasks
). This inner list is vertical and should wrap into columns when needed. When wrapping into more columns, its width should increase to make room for more items. This width increase should apply also to the containing item of the outer list.
此列表 ( ul#main?>?li
) 的每个项目都有一个标题 ( ul#main?>?li?>?h2
) 和一个内部列表 ( ul#main?>?li >?ul.tasks
)。这个内部列表是垂直的,需要时应该包装成列。当包装成更多列时,它的宽度应该增加,以便为更多项目腾出空间。这种宽度增加也应适用于外部列表的包含项。
.tasks {
flex-direction: column;
flex-wrap: wrap;
/* ...and more... */
}
My problem is that the inner lists don't wrap when the height of the window gets too small. I have tried lots of tampering with all the flex properties, trying to follow the guidelines at CSS-Tricksmeticulously, but no luck.
我的问题是当窗口的高度太小时,内部列表不会换行。我已经尝试了大量篡改所有 flex 属性,试图仔细遵循CSS-Tricks的指导方针,但没有运气。
This JSFiddleshows what I have so far.
这个JSFiddle显示了我到目前为止所拥有的。
Expected result(what I want):
预期结果(我想要的):
Actual result(what I get):
实际结果(我得到的):
Older result(what I got in 2015):
较旧的结果(我在 2015 年得到的):
UPDATE
更新
After some investigation, this is beginning to look like a bigger issue. All major browsers behave the same way, and it has nothing to do with my flexbox design being nested. Even simpler flexbox column layouts refuse to increase the list's width when the items wrap.
经过一番调查,这开始看起来像是一个更大的问题。所有主流浏览器的行为方式都相同,这与我的 flexbox 设计嵌套无关。更简单的 flexbox 列布局在项目换行时拒绝增加列表的宽度。
This other JSFiddleclearly demonstrates the problem. In current versions of Chrome, Firefox and IE11, all items wrap correctly; the list's height increases in row
mode, but its width does not increase in column
mode. Also, there is no immediate reflow of elements at all when changing the height of a column
mode, but there is in row
mode.
这个另一个 JSFiddle清楚地说明了这个问题。在当前版本的 Chrome、Firefox 和 IE11 中,所有项目都正确换行;列表的高度在row
模式下增加,但其宽度在column
模式下不增加。此外,在更改column
模式的高度时根本没有元素立即回流,但有row
模式。
However, the official specs (look specifically at example 5)seem to indicate that what I want to do should be possible.
但是,官方规范(具体看示例 5)似乎表明我想做的事情应该是可能的。
Can someone come up with a workaround to this problem?
有人可以想出解决这个问题的方法吗?
UPDATE 2
更新 2
After a lot of experimenting using JavaScript to update the height and width of various elements during resize events, I have come to the conclusion that it is too complex and too much trouble to try to solve it that way. Also, adding JavaScript definitely breaks the flexbox model, which should be kept as clean as possible.
在多次尝试使用 JavaScript 在 resize 事件期间更新各种元素的高度和宽度之后,我得出的结论是,尝试以这种方式解决它太复杂且太麻烦。此外,添加 JavaScript 肯定会破坏 flexbox 模型,它应该尽可能保持干净。
For now, I'm falling back to overflow-y: auto
instead of flex-wrap: wrap
so that the inner container scrolls vertically when needed. It is not pretty, but it is one way forward that at least does not break useability too much.
现在,我要回退到overflow-y: auto
而不是flex-wrap: wrap
让内部容器在需要时垂直滚动。它并不漂亮,但它是一种前进的方式,至少不会过多地破坏可用性。
回答by Michael Benjamin
The Problem
问题
This looks like a fundamental deficiency in flex layout.
这看起来像是 flex 布局的一个根本缺陷。
A flex container in column-direction will not expand to accommodate additional columns. (This is not a problem in flex-direction: row
.)
列方向的 flex 容器不会扩展以容纳额外的列。(这不是问题flex-direction: row
。)
This question has been asked many times (see list below), with no clean answers in CSS.
这个问题已经被问过很多次(见下面的列表),在 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?
所有主要浏览器怎么可能让 flex 容器在行方向而不是列方向上扩展?
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.
更新:该问题似乎已在 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/
OP 创建了一个有用的演示来说明问题。我在这里复制它:http: //jsfiddle.net/nwccdwLw/1/
Workaround Options
解决方法选项
Hacky solutions from the Stack Overflow community:
来自 Stack Overflow 社区的 hacky 解决方案:
More Analysis
更多分析
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?
- 弹性盒容器宽度不会增长
- 如何使 display:flex 容器与其包裹的内容水平展开?
- Flex-flow:列包装。如何设置容器的宽度等于内容?
- Flexbox flex-flow 列包裹 chrome 中的错误?
- 如何使用“flex-flow:列换行”?
- 当内容包裹在一列中时,Flex 容器不会扩展
- flex-flow: 列包装,在一个 flex box 中导致父容器溢出
- Html flexbox 容器不会扩展到包裹的孩子
- Flexbox 容器和溢出的 flex 孩子?
- 如何制作一个可拉伸以适合包裹物品的 flexbox 容器?
- Flex容器计算一列,当有多列时
- 使用 flex 使容器全宽
- Flexbox 容器可以调整大小吗?
- Flex-Wrap Inside Flex-Grow
- Flexbox 增长到包含
- 将 flexbox 元素展开为其内容?
- flexbox 列拉伸以适应内容
- https://stackoverflow.com/q/48406237/3597276
- flex-flow:列换行不会拉伸父元素的宽度
- 为什么我的 <ul> 不扩展宽度以覆盖所有 <li>?
- flexbox 列环绕时如何调整宽度?
- Flexbox wrap 没有增加父级的宽度?
回答by MandeeD
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
我在 CodePen 上有一个示例,可以在 flexbox 问题和网格修复之间切换:https://codepen.io/MandeeD/pen/JVLdLd
回答by Itay Gal
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.
由于尚未提出任何解决方案或适当的解决方法,因此我设法通过稍微不同的方法获得了请求的行为。我没有将布局分成 3 个不同的 div,而是将所有项目添加到 1 个 div 中,并在其间创建更多 div 的分隔。
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.
建议的解决方案是硬编码的,假设我们有 3 个部分,但可以扩展到通用部分。主要思想是解释我们如何实现这种布局。
- Adding all the items into 1 container div that uses flex to wrap the items
- 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.
- Using
:before
on each first item, we can locate the title of each section. - Using
space
creates the gap between the sections - 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. - 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
. - To get the correct width of each background, I'm using JS, setting the correct width, and also adding a listener to resize.
- 将所有项目添加到 1 个使用 flex 包装项目的容器 div 中
- 每个“内部容器”的第一项(我将其称为节)将有一个类,它帮助我们进行一些操作,以创建每个节的分隔和样式。
- 使用
:before
上的每个第一个项目,我们可以找到每个部分的标题。 - 使用
space
创建部分之间的间隙 - 由于
space
不会覆盖该部分的全部高度,我还将添加:after
到这些部分中,因此将其定位为绝对位置和白色背景。 - 为了设计每个部分的背景颜色,我在每个部分的第一项内添加了另一个 div。我也将处于绝对位置,并且将具有
z-index: -1
. - 为了获得每个背景的正确宽度,我使用 JS,设置正确的宽度,并添加一个监听器来调整大小。
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>
回答by user2323336
Possible JS solution..
可能的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");
}
}