0

Let me start from a tiny example based on display:flex;.

#container {
  display: flex;
  align-items: flex-start;
  flex-wrap: wrap;
  width: 150px;
}
.content {
  border: 1px solid black;
  display: inline-block;
  padding: 5px;
}
<div id="container">
  <div class="content">content</div>
  <div class="content">content <br/> big</div>
  <div class="content">content</div>
  <div class="content">content</div>
  <div class="content">content</div>
  <div class="content">content</div>
  <div class="content">content</div>
  <div class="content">content</div>
</div>

As you can see here, when there is a difference between component height in one row, empty space will appear near smaller component.
It will not happen when using flex-direction: column; but in this case height must be setted. I want to make a grid of unlimited height, with 2 columns, and items height can be extended when user clicks on it (to see additional info).
I also tried display: grid; (results was the same as with flex) and columns: 2 with presetted columns width.
With columns: 2 it almost worked, but sometimes when item height extends items from one column goes to another, which looks pretty bad.
So the question is there any way to do that kind of grid on pure css. Easiest way I see is in using display: flex; with flex-direction: column; but with javascript calculated height for container.But I want to avoid using javascript for styling as much as I can.

Thank you for any advise!

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701

1 Answers1

1

You were on the right track with the columns property. To solve the problem of an item in the column splitting across columns, you can wrap each column item in another element that has display: inline-block.

Make sure to also either set the inline-block element to 100% width or wrap it in yet another element with a block-type display (block, flex, grid) in order to prevent two particularly small children from sitting side-by-side within a column. (Unless that's something you'd want.)

#container {
  column-count: 2;
  column-gap: 20px;
  width: 160px;
}
.content-outer {
  width: 100%;
  display: inline-block;
}
.content {
  width: 100%; /* width as related to the column, not the whole container */
  border: 1px solid black;
  padding: 5px;
}
<div id="container">
  <div class="content-outer">
    <div class="content">content</div>
  </div>
  <div class="content-outer">
    <div class="content">content <br/> big</div>
  </div>
  <div class="content-outer">
    <div class="content">content</div>
  </div>
  <div class="content-outer">
    <div class="content">content</div>
  </div>
  <div class="content-outer">
    <div class="content">content</div>
  </div>
  <div class="content-outer">
    <div class="content">content</div>
  </div>
  <div class="content-outer">
    <div class="content">content</div>
  </div>
  <div class="content-outer">
    <div class="content">content</div>
  </div>
</div>
cjl750
  • 4,380
  • 3
  • 15
  • 27
  • Thank you! That's very interesting. Can you please explain a bit why is that works? – Александр Чиркин May 02 '20 at 00:16
  • @АлександрЧиркин So, in a general sense, the "inline" half of `inline-block` will make the element behave as one, single inline element, such as an input or image. You can imagine how it wouldn't make sense to allow either of those to split across columns. Only block-level elements are allowed to break across columns, allowing their children to be divvied up between columns. So this way you get the best of both worlds – your element won't split across columns but will still act as a block for layout purposes. – cjl750 May 02 '20 at 00:47
  • @АлександрЧиркин Also note the edit I just made for info on a potential gotcha with this trick. – cjl750 May 02 '20 at 00:50