18

When using flex box in default row direction, the container height grows to contain all the flex items, even if it is absolutely positioned.

#container {
  position: absolute;
  display: flex;
  flex-wrap: wrap;
}

#container > div {
  flex: 0 0 200px;
  height: 200px;
}

See http://codepen.io/tamlyn/pen/dPjLoN/?editors=110

However if the flex direction is changed to column, the container collapses to the width of a single flex item, even if the items wrap onto the next column.

#container {
  position: absolute;
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
}

#container > div {
  flex: 0 0 200px;
  width: 200px;
}

See http://codepen.io/tamlyn/pen/rarbeN?editors=110

How can I make the container contain all flex items in column mode?

Tamlyn
  • 22,122
  • 12
  • 111
  • 127

3 Answers3

4

I've actually found a CSS-only solution to this but it isn't the most perfect thing in the world. Here it is: http://codepen.io/anon/pen/vEPBKK

The trick here is to create a visibility: collapsed container. In flex, visibility: collapsed objects take themselves out of the normal flex flow but retain their dimensions for the purpose of layout. This widens the flex container to the desired width but leaves the flex items unaffected. There are a few caveats, however:

  1. This requires a bit of fiddling. As you can see, the magic <div> is a set width but it uses :nth-child to determine how many boxes are before it. If your actual design breaks at more or less than 3 rows, you'll have to adjust this and you'll most certainly have to adjust the width of the object.
  2. Because of a rendering bug, this does not work in IE. Luckily, IE's incorrect implementation does exactly what you wanted in the first place without any changes so all you have to do is give IE it's own stylesheet with some conditional statements and shoot the div.magic some good old display: none.

HTML

<div id="container">
  <div class="fb"></div>
  <div class="fb"></div>
  <div class="fb"></div>
  <div class="fb"></div>
  <div class="fb"></div>
  <div class="fb"></div>
  <div class="fb"></div>
  <div class="magic"></div>
</div>

CSS

#container {
  position: absolute;
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  border: 1px solid #f00;
  height: 650px;
  padding: 1px;
}

#container div.fb {
  border: 1px solid #555;
  flex: 0 0 200px;
  background-color: #ccc;
  width: 200px;
  margin: 1px;
  height: 200px;
}

#container > div.magic {
  height: 0;
  margin: 0;
  padding: 0;
  visibility: collapsed;
}

#container > div.magic:nth-child(5),
#container > div.magic:nth-child(6),
#container > div.magic:nth-child(7) {
  width: 408px;
}

#container > div.magic:nth-child(8),
#container > div.magic:nth-child(9),
#container > div.magic:nth-child(10) {
  width: 612px;
}

#container > div.magic:nth-child(11),
#container > div.magic:nth-child(12),
#container > div.magic:nth-child(13) {
  width: 816px;
}
Joshua Whitley
  • 1,196
  • 7
  • 21
  • 1
    As far as I can tell, `collapsed` [isn't a valid value for the visibility property](https://developer.mozilla.org/en-US/docs/Web/CSS/visibility). `collapse` is, but your `magic` div seems to work with or without the `visibility` property, which makes me even more confused about what's going on here. – Michael Martin-Smucker Nov 11 '15 at 16:17
  • The way it works is that the div.magic essentially is setting a "width" property on the container, but by setting it on a child you can use nth-child to essentially "count" the children using CSS. It's hacky as all hell, will only work for the number of elements you directly code it to work for, and involves fiddling with pixel values until you get something that works - but I'm nonetheless impressed by the simplicity and straightforwardness of it. – Chris Browne Feb 01 '17 at 19:35
0

I think this is the CSS you're looking for:

#container {
  display: flex;
  flex-flow: row wrap;
  border: 1px solid #f00;
  padding: 1px;
}

#container > * {
  border: 1px solid #555;
  background-color: #ccc;
  height: 200px;
  width: 200px;
  margin: 1px;
}

The "Container" will always the the width of it's container, in this case the page, but now the boxes will adjust within it properly.

Let me know if I misunderstood your question.

Update

I've been playing with what you're asking for for several days now, and it really seems like it's not possible to do what you're asking... at least not in the direction that you're asking.

The container wants to be the maximum width possible. Unless you force the container to be the exact width, at which point it wont be the full width, but it wont flex with the flexing content either.

Pixel Rubble
  • 1,104
  • 3
  • 14
  • 26
  • Isn't that just the same as my first example? What I'm looking for is that behaviour but in column mode rather than row. – Tamlyn Mar 18 '15 at 11:30
  • If you do `flex-flow: column wrap;` then you'll get your column mode, but I don't think **that's** what you're looking for cause then they all just stack vertically and do nothing horizontally. With it this way, they become a column as needed. But it might be. – Pixel Rubble Mar 18 '15 at 11:35
  • I've added numbering to the boxes in the codepens to better illustrate what I mean. – Tamlyn Mar 27 '15 at 09:54
  • I think this is the only way too approach this but setting a max-width to #container. That way you can determine the max number of columns you want and stretch the content vertically. – Kinburn101 Mar 30 '15 at 09:29
-3

.flex-container {
  padding: 0;
  margin: 0;
  list-style: none;
  
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  
  -webkit-flex-flow: row wrap;
  justify-content: space-around;
  border: 1px solid #f00;
}

.flex-item {
  background-color: #ccc;
  padding: 5px;
  width: 200px;
  height: 150px;
  line-height: 150px;
  color: white;
  font-weight: bold;
  font-size: 3em;
  text-align: center;
  border: 1px solid #555;
}
<div id="container" class="flex-container">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
  <div class="flex-item">3</div>
  <div class="flex-item">4</div>
  <div class="flex-item">5</div>
  <div class="flex-item">6</div>
  <div class="flex-item">7</div>
</div>

The first try I do not understand what you mean as reference material you can see this tutorial https://css-tricks.com/snippets/css/a-guide-to-flexbox/

bro no
  • 43
  • 4