How to Make a Display:Flex Container Expand Horizontally with Its Wrapped Contents

How can I make a display:flex container expand horizontally with its wrapped contents?

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

container width = position of the last child - position of the container + width of the last child (including margin)

Code :

$(document).ready(function() {
$('.container').each(function( index ) {
var lastChild = $(this).children().last();
var newWidth = lastChild.position().left - $(this).position().left + lastChild.outerWidth(true);
$(this).width(newWidth);
})
});

Demo :

http://jsfiddle.net/qzea320L/

Fill the remaining height or width in a flex container

Use the flex-grow property to make a flex item consume free space on the main axis.

This property will expand the item as much as possible, adjusting the length to dynamic environments, such as screen re-sizing or the addition / removal of other items.

A common example is flex-grow: 1 or, using the shorthand property, flex: 1.

Hence, instead of width: 96% on your div, use flex: 1.


You wrote:

So at the moment, it's set to 96% which looks OK until you really squash the screen - then the right hand div gets a bit starved of the space it needs.

The squashing of the fixed-width div is related to another flex property: flex-shrink

By default, flex items are set to flex-shrink: 1 which enables them to shrink in order to prevent overflow of the container.

To disable this feature use flex-shrink: 0.

For more details see The flex-shrink factor section in the answer here:

  • What are the differences between flex-basis and width?

Learn more about flex alignment along the main axis here:

  • In CSS Flexbox, why are there no "justify-items" and "justify-self" properties?

Learn more about flex alignment along the cross axis here:

  • How does flex-wrap work with align-self, align-items and align-content?

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

Make flex items wrap in a column-direction container

Block-level elements, by default, take up the full width of their containing block. This, in effect, resolves to width: 100%, which sets a break in the flow of content in the horizontal direction.

So, flex items can wrap by default in a row-direction container.

Nothing in HTML or CSS, however, sets a default height on block-level elements. Heights are content-driven (height: auto).

This means that elements will flow vertically without having any reason to break.

(I guess somewhere along the line of evolution, possibly on the basis of usability studies, it was decided that it would be okay for web applications to expand vertically, but not horizontally.)

That's why flexbox doesn't automatically wrap items in column direction. It requires an author-defined height to serve as a breaking point.


Often times, however, a layout's height is dynamic so a specific height cannot be set. That makes flexbox unusable for wrapping items in column direction. A great alternative is CSS Grid Layout, which doesn't require a height setting on the container:

div {  display: grid;  grid-gap: 10px;}
p:nth-child(3n + 1) { grid-row: 1; background-color: aqua;}
p:nth-child(3n + 2) { grid-row: 2; background-color: orange;}
p:nth-child(3n + 3) { grid-row: 3; background-color: lightgreen;}
p { margin: 0; padding: 10px;}
<div>  <p>ONE</p>  <p>TWO</p>  <p>THREE</p>  <p>FOUR</p>  <p>FIVE</p>  <p>SIX</p>  <p>SEVEN</p>  <p>EIGHT</p>  <p>NINE</p></div>

Flexbox wrapped content and resizing

I guess you can set:

  1. white-space: nowrap and flex: 0 1 auto for the second div,

  2. flex: 1 for the first div

See demo below:

body {  margin: 0;}* {  box-sizing: border-box;}.container {  display: flex;  flex-direction: row;  flex-wrap: wrap;}.container > div {  border: 1px solid red;}.container div:nth-child(1) {  flex:1;}.container div:nth-child(2) {  white-space: nowrap;  flex:0 1 auto;}.container div:nth-child(3),.container div:nth-child(4) {  flex-basis: 100%;}
<div class="container">  <div>FIRST itema has    <br/>longer multiline longer multiline longer multiline longer multiline longer multiline longer multiline longer multiline     <br/>text content</div>  <div>Some text content here and some more</div>  <div>Some text</div>  <div>Some text here</div></div>

How to make a flex column container shrinks to its content

I finally get the answer by myself

Actually it seems that it cannot be made only by CSS due to different browser behaviors regarding the flexbox implementation

Code :

$(document).ready(function() {
$('.vertical').each(function( index ) {
var lastChild = $(this).children().last();
var newWidth = lastChild.position().left - $(this).position().left + lastChild.outerWidth(true);
$(this).width(newWidth);
})
});

Demo :

http://jsfiddle.net/btuspmz6/2/

Use flex column with wrap in a div taking up all remaining space

First, I tried adding a fixed height to the flex parent and that seemed to work but was not a very elegant solution. So I settled on this :)
Adding the overflow parameter seemed to do the trick.

<link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.0.2/tailwind.min.css" rel="stylesheet"/>
<div class="flex flex-col bg-blue-100 h-screen">
<h1 class="text-center text-3xl bg-blue-200 py-2">My Header</h1>

<div class="flex-auto flex flex-col flex-wrap overflow-auto">
<div class="bg-blue-300 border-2 border-black h-16 w-12"></div>
<div class="bg-blue-300 border-2 border-black h-16 w-12"></div>
<div class="bg-blue-300 border-2 border-black h-16 w-12"></div>
<div class="bg-blue-300 border-2 border-black h-16 w-12"></div>
</div>
</div>


Related Topics



Leave a reply



Submit