Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

html

css

flexbox

When using css flexbox the three main browsers appear to behave entirely differently in certain areas.

In this case I am trying to create a grid of images:

<div class="container">      <div class="photo"></div>      <div class="photo"></div>      <div class="photo"></div>      <div class="photo"></div>      <div class="photo"></div>      <div class="photo"></div> </div>   .container {     display:inline-flex;     flex-flow : column wrap;     align-content : flex-start;     height : 100%; } 

In this example I need a container, itself containing several div elements set up to flow from top to bottom and wrapping when they reach the bottom. Ultimately providing me with columns of photos.

However I need the container to expand horizontally to accommodate the wrapped elements:

Here is a quick jsFiddle to demonstrate.

The behaviour is as follows:

  • IE 11 - Correct, the container stretches horizontally to wrap each column of wrapped elements
  • Firefox - The container only wraps the first column of elements, with the rest overflow out.
  • Chrome - The container always stretches to fill the width of its parent, whatever that may be.

In this instance I would like to achieve the behaviour of IE11 in the other two browsers. Therefore my question is, how can I make a flexbox container expand horizontally to match its column wrap contents.

Thanks in advance.

like image 338
gordyr Avatar asked May 01 '14 13:05

gordyr


People also ask

How do you wrap text in a Flex container?

As you only want the text itself to wrap you need to use flex-wrap: nowrap; to keep . right on the same line. The text will automatically wrap when there is not enough space.

Which property is used to align Flex items horizontally?

The align-content property is used to align the flex lines.

How do you align Flex items horizontally and vertically?

In order to vertically and/or horizontally center text or other content contained in a flex item, make the item a (nested) flex container, and repeat the centering rules. More details here: How to vertically align text inside a flexbox? Alternatively, you can apply margin: auto to the content element of the flex item.


2 Answers

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. This will swap the block direction with the inline direction, and thus the flex items will flow vertically. Then you only need to restore the horizontal writing mode inside the flex items.

.container {    display: inline-flex;    writing-mode: vertical-lr;    flex-wrap: wrap;    align-content: flex-start;    height: 350px;    background: blue;  }  .photo {    writing-mode: horizontal-tb;    width: 150px;    height: 100px;    background: red;    margin: 2px;  }
<div class="container">    <div class="photo">1</div>    <div class="photo">2</div>    <div class="photo">3</div>    <div class="photo">4</div>    <div class="photo">5</div>    <div class="photo">6</div>    <div class="photo">7</div>    <div class="photo">8</div>    <div class="photo">9</div>  </div>

This approach may have its own bugs in edge cases, especially if you mix advanced layout techniques like floats and nested flexboxs. But for most cases it seems to work properly.

like image 92
Oriol Avatar answered Oct 01 '22 02:10

Oriol


The spec says that what you're doing should work, but it's implemented incorrectly in every major browser besides Internet Explorer / Edge, making multi-line inline-flex column layouts useless at present for most developers. Here's a Chromium bug report providing an example that is effectively identical to yours, and noting that it renders incorrectly in Chrome, Safari, and Firefox.

The argument from spec is more complicated than I'm able to understand, but the key point is that Flexible Box Layout Module Level 1 spec defines the intrinsic cross-size of a flex container (that is, the intrinsic height of a flex-direction: row flex container or the intrinsic width of a flex-direction: column flex container) in the section Flex Container Intrinsic Cross Size. There, it is stated:

For a multi-line flex container, the min-content/max-content cross size is the sum of the flex line cross sizes

That is, the intrinsic width of a flex-direction: column flex container should be the sum of the widths of its columns, as you'd expect. (There is more complexity than this, and I don't understand it all, but I believe the above to be broadly true.) However, Chrome, Firefox, and Safari all calculate this width incorrectly; setting width: min-content or width: max-content on a column wrap flex box in Chrome, you can clearly see that the width is set to the width of the widest single element.

A silly Chrome-specific workaround exists, but is probably best avoided. Until the bug is fixed, this part of the Flexbox model simply doesn't work as designed and there's no clean solution available.

like image 27
Mark Amery Avatar answered Oct 01 '22 03:10

Mark Amery