When flexbox items wrap in column mode, container does not grow its width
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>?
- 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
Equal width flex items even after they wrap
Currently, flexbox offers no clean solution for aligning flexible items in the last row or column. It's beyond the scope of the current spec.
Here's more information and various solutions people have used to get around the problem:
- Targeting flex items on the last row
- Is it possible for flex items to align tightly to the items above them?
However, last-row alignment is not a problem with another CSS3 technology, Grid Layout. In fact, it's very simple with this method (and requires no changes to the HTML):
.container { display: grid; grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); grid-auto-rows: 20px; grid-gap: 5px;}
.item { background: yellow; text-align: center; border: 1px solid red;}
<div class="container"> <div class="item">1</div> <div class="item">2</div> <div class="item">3</div> <div class="item">4</div> <div class="item">5</div> <div class="item">6</div> <div class="item">7</div> <div class="item">8</div> <div class="item">9</div> <div class="item">10</div></div>
Make flex items have equal width in a row
Flexbox method
In order to make the text items (.section-child
) equal width, you need to use flex: 1 1 0
, which you have done. This is the same as saying flex: 1
.
However, this by itself doesn't achieve the goal for two reasons:
The parent of
.section-child
, a flex container, but also a flex item in a larger container, is limited to the width of its content, by default. So it won't expand and the text can overflow the container. You need to applyflex: 1
to.section
, as well.A flex item cannot be smaller than the size of its content, by default. The initial setting is
min-width: auto
. Soflex: 1
cannot work to equally distribute container space, because a flex item cannot shrink past the longest item. You need to override this behavior withmin-width: 0
.
.top-level { display: flex; flex-flow: row wrap;}
.section { display: flex; flex-flow: row nowrap; border: 1px solid; margin-right: 12px; margin-top: 12px; flex: 1; min-width: 0;}
.section-child { display: flex; flex-flow: column nowrap; align-items: center; flex: 1; min-width: 0;}
.child-title { white-space: nowrap;}
.vertical-separator { width: 1px; background-color: rgba(0, 0, 0, 0.3); margin: 8px;}
<div class="top-level"> <section class="section"> <div class="section-child"> <h4 class="child-title">Title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Longer title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Much much longer title</h4> <!--A lot more content here--> </div> </section> <section class="section"> <div class="section-child"> <h4 class="child-title">Title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Longer title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Much much longer title</h4> <!--A lot more content here--> </div> </section> <section class="section"> <div class="section-child"> <h4 class="child-title">Title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Longer title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Much much longer title</h4> <!--A lot more content here--> </div> </section></div>
Dynamic width flexboxes that wrap yet keep column structure?
You can do this with CSS grid layout, using grid-template-columns
. With minmax(200px, 1fr)
you can set min-width of each column to 200px
and max-width to one track of grid layout. You also need to use auto-fit
to make tracks take full width in case there is available space.
.container { padding: 20px; display: grid; background: white; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));}
.container > div { border: 1px solid black; background: #ececec; margin: 5px; padding: 10px; margin-left: 10px;}
<div class="container"> <div>Div 1</div> <div>Div 2</div> <div>Div 3</div> <div>Div 4</div></div>
Flexbox: wrong width calculation when flex-direction: column, flex-wrap: wrap
This appears to be yet another bug in the Flexible Box Layout Module involving flex-direction: column
and flex-wrap: wrap
.
Browsers seem to be all over the place on this issue.
In this particular case, as stated in a bug report:
It seems to me that the width is calculated as if the inside elements were laid out horizontally (
flex-direction: row
) instead of vertically.
In other cases, the opposite occurs:
- When flexbox items wrap in column mode, container does not grow its width
In both cases, there are currently no flex methods to resolve the problem.
For this particular question, one developer offers a CSS workaround, but I'm not sure it works in all browsers. I wouldn't recommend it unless you're truly desperate:
In some instances, you may be able to workaround this issue by using
vertical writing mode.That is, instead of using
flex-direction: column;
, use
flex-direction: row; writing-mode: vertical-lr;
. Remember to reset
towriting-mode: initial;
in the children of the flexbox.https://bugs.chromium.org/p/chromium/issues/detail?id=507397
Bug reports:
- https://bugs.chromium.org/p/chromium/issues/detail?id=247963
- https://bugs.chromium.org/p/chromium/issues/detail?id=507397
- https://bugzilla.mozilla.org/show_bug.cgi?id=995020
- https://codereview.chromium.org/289903007
- https://src.chromium.org/viewvc/blink?view=revision&revision=178925
How to make flex container width adapt to the width (and numbers) of flex items?
You could use a single grid (instead nested flexbox) and set the input on the first row among and before the cards.
here is an example of the idea or a codepen with a side element https://codepen.io/gc-nomade/pen/NWpVeOY :
* {
box-sizing: border-box;
}
.mainContainer {
min-height: 200px;
padding: 1rem;
}
#search {
width: 100%;
height: 2rem;
background-color: var(--Mwhite);
border: 0.05rem solid var(--Mdefault);
border-radius: 0.5rem;
color: var(--Mdefault);
padding: 0 0 0 0.5rem;
outline: 0.05rem solid transparent;
transition: outline 0.5s;
grid-column: 1 / -1;
}
.secondaryContainer {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(12.5rem, max-content));
justify-content: center;
row-gap: 1rem;
column-gap: 0.5rem;
}
.card {
background-color: var(--Mwhite);
border: 0.05rem solid var(--Mdefault);
width: 12.5rem;
height: fit-content;
min-height: 16.25rem;
display: flex;
flex-flow: column nowrap;
align-items: center;
justify-content: space-between;
box-shadow: var(--Mdefault) 0 0 0;
transition: box-shadow 0.5s, border 0.5s;
border-radius: 0.8rem;
}
input#search,
.card {
border: 1px solid black;
;
}
<div class="mainContainer">
<div class="secondaryContainer">
<input type="search" placeholder="search" id="search" />
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
</div>
</div>
Flexbox for fixed-height container that wraps items and has dynamic width
You can use grid's autofill property, so you don't need to know the number of columns.
.my-container {
display: grid;
grid-auto-flow: column;
grid-template-rows: repeat(auto-fill, minmax(45px, 1fr));
background-color: rgb(33, 150, 243);
padding: 15px;
height: 600px;
width: fit-content;
}
.my-item {
width: 250px;
height: 25px;
color: white;
padding: 10px;
flex: 0 0 auto;
}
JSFiddle Demo: https://jsfiddle.net/92sak0zc/6/
CSS Flexbox: 3 flex items, 2 Columns (widths equal to content) and 1 item that grows to width
I ended up just adding a container around all of the items except the first one and using flex to make them grow as needed.
Benefits:
- The first item can be however long it wants and the other items will grow to match it’s width.
- There can be an infinite amount of flex items and the first item will grow to match their combined width.
If anyone does find a method that retains these benefits without adding extra markup, please let us know!
https://codepen.io/albrechtnate/pen/YzzLzLV
.container { background-color: #ccc; width: fit-content;}
.container > div:first-child { background-color: blue;}
.container .group { background-color: teal; display: flex;}
.container .group div { background-color: red; flex: 1 0 auto;}
<div class="container"> <div>Item</div> <div class="group"> <div>Item Two</div> <div>Item Three</div> </div></div>
<br>
<div class="container"> <div>Item</div> <div class="group"> <div>Item Two</div> <div>Item Three</div> <div>Item Four</div> <div>Item Five</div> </div></div>
<br>
<div class="container"> <div>Item - This one is super duper extra looper long.</div> <div class="group"> <div>Item Two</div> <div>Item Three</div> </div></div>
Related Topics
Is Position: Static Identical to Position: Relative, with No Other Properties Specified
Wicked_Pdf Stylesheet Not Working on Heroku
Remove White Space Under Footer
CSS Takes Effect After Page Has Rendered
Chrome Not Loading CSS Source Maps
How to Force Nested List Items to Be The Same Width as Parent List Item
Resize Images as Viewport Resizes Without Sides Being Cut Off
How to Include a CSS Stylesheet in Orchard Module
Unnoticeable Lesscss Compiler in Eclipse Pdt
React Js: Apply Material-Ui CSSbaseline
Twitter Bootstrap Grid Vertical Align Bottom
Parent Div with Height: 100% Doesn't Work
Large Iconfont Icon Cut Off on The Right Side
Strange Border-Width Behavior in Chrome - Floating Point Border-Width
CSS3 Transition - Change Animation "Anchor Point"