0

Let's say that I have the following HTML code.

<div class='container'>
    <div style='width: 50px; height: random' class='col1'>1</div>
    <div style='width: 50px; height: random' class='col3'>2</div>
    <div style='width: 50px; height: random' class='col2'>3</div>
    <div style='width: 50px; height: random' class='col3'>4</div>
    <div style='width: 50px; height: random' class='col1'>5</div>
    <div style='width: 50px; height: random' class='col2'>6</div>
    <div style='width: 50px; height: random' class='col1'>7</div>
    <div style='width: 50px; height: random' class='col3'>8</div>
    <div style='width: 50px; height: random' class='col2'>9</div>
</div>

<!-

|1| |3| |2| // height of 2 is greater
|5| |6| | | // height of 5 is greater
| | |9| |4| // height of 9 is greater
|7| | | |8|

->

I want container to have 3 columns. I also want each child to be sorted into one of those columns based on its class. Obviously, it would be easy to do this with JavaScript but I'm wondering if it's possible to do it with CSS.

.grid {
  -webkit-column-count: 3;
  -webkit-column-gap: 10px;
  -webkit-column-fill: auto;
  -moz-column-count: 3;
  -moz-column-gap: 10px;
  -moz-column-fill: auto;
  column-count: 4;
  column-gap: 15px;
  column-fill: auto;
}
.block {
  background-color: #ee01ca;
  display: block;
  padding: 20px;
  word-wrap: break-word;
  margin-bottom: 20px;
  -webkit-column-break-inside: avoid;
  -moz-column-break-inside: avoid;
  column-break-inside: avoid;
}

.one {
  height: 100px;
}

.two {
  height: 200px;
}

.three {
  height: 300px;
}
<div class="grid">
  <div class="block one">ervewrv</div>
  <div class="block two">afrvewrwerb</div>
  <div class="block three">dfvdsf</div>
  <div class="block one">vdfvdf</div>
  <div class="block two">dfw45g4</div>
  <div class="block one">ervewrv</div>
  <div class="block two">afrvewrwerb</div>
  <div class="block three">dfvdsf</div>
  <div class="block one">vdfvdf</div>
  <div class="block two">dfw45g4</div>
  <div class="block three">4rv4r</div>
  <div class="block one">4rv454</div>
  <div class="block three">4rv4r</div>
  <div class="block one">4rv454</div>
  <div class="block one">ervewrv</div>
  <div class="block one">ervewrv</div>
  <div class="block two">afrvewrwerb</div>
  <div class="block three">dfvdsf</div>
  <div class="block one">vdfvdf</div>
  <div class="block two">dfw45g4</div>
  <div class="block three">4rv4r</div>
  <div class="block one">4rv454</div>
  <div class="block one">ervewrv</div>
  <div class="block two">afrvewrwerb</div>
  <div class="block three">dfvdsf</div>
  <div class="block one">vdfvdf</div>
  <div class="block two">dfw45g4</div>
  <div class="block three">4rv4r</div>
  <div class="block one">4rv454</div>
  <div class="block two">afrvewrwerb</div>
  <div class="block three">dfvdsf</div>
  <div class="block one">vdfvdf</div>
  <div class="block two">dfw45g4</div>
  <div class="block one">ervewrv</div>
  <div class="block two">afrvewrwerb</div>
  <div class="block three">dfvdsf</div>
  <div class="block one">vdfvdf</div>
  <div class="block two">dfw45g4</div>
  <div class="block three">4rv4r</div>
  <div class="block one">4rv454</div>
  <div class="block three">4rv4r</div>
  <div class="block one">4rv454</div>
</div>

This is similar to the effect I'm after except I need the sorting to be done left to right. So in the example, ervewrv should be left of afrvewrwerb.

Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
jscul
  • 748
  • 1
  • 10
  • 25
  • everything is random ? number of element, height, ? – Temani Afif Feb 16 '18 at 22:52
  • The number of children is dynamic along with the height of each child. There is a maximum value for the height but I don't think that changes anything. – jscul Feb 16 '18 at 22:54
  • 1
    no sure if you can find a solution with pure CSS .. but you can check flex and the order property ... at least you can re-roder your element then you have to find how to setup the column – Temani Afif Feb 16 '18 at 22:56
  • Yeah, I was looking into that earlier and couldn't find the solution there. – jscul Feb 16 '18 at 23:03

1 Answers1

1

CSS grid may work for your layout.

Use grid-column value to order your content.

.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: 15px;
  grid-auto-flow: dense;
}

.container >div {
  width: 50px;
  height: 50px;
  background: pink;
}

.col1 {
  grid-column: 1;
}

.col2 {
  grid-column: 2;
}

.col3 {
  grid-column: 3;
}
<div class='container'>
  <div class='col1' style="height: 80px;">1</div>
  <div class='col3'>2</div>
  <div class='col2'>3</div>
  <div class='col3' style="height: 100px;">4</div>
  <div class='col1'>5</div>
  <div class='col2'>6</div>
  <div class='col1'>7</div>
  <div class='col3'>8</div>
  <div class='col2'>9</div>
</div>
sol
  • 22,311
  • 6
  • 42
  • 59
  • That's essentially what I'm looking for. Is there a way to get the grid items height to be dynamic? In other words, can each grid items height be independent of the row it's in? **EDIT: In your example, the second column would be the shortest column.** – jscul Feb 16 '18 at 23:49
  • I don't think so. You're describing a masonry layout. This question might be of some use: https://stackoverflow.com/questions/43917346/masonry-layout-with-css-grid – sol Feb 16 '18 at 23:53
  • @JohnCullen nope, the closest you can get is to have variable row spans on the elements, but not dynamic heights. CSS Grid will always behave... as a grid. – Facundo Corradini Feb 17 '18 at 01:00