Ecir Hana
Ecir Hana

Reputation: 11468

Structure of 3 column layout

I would like to make three column layout with CSS. Is it possible that the column items flow in arbitrary order and I only "assign" them to a given column or do they have to be structured so that they first fill the first column, then the second and third? The items have the same width, but different height. Also, the columns may each have vastly different number of items. For example:

(1) For a structure:

container:
#1 div .red
#2 div .green
#3 div .green
#4 div .blue
#5 div .red
#6 div .green
#7 div .blue

is it possible to style it with CSS so that it falls into three columns like:

.red       .green     .blue
+--------+ +--------+ +--------+
|#1      | |#2      | |#4      |
|        | +--------+ |        |
+--------+ +--------+ |        |
+--------+ |#3      | |        |
|#5      | |        | +--------+
|        | +--------+ +--------+
|        | +--------+ |#7      |
|        | |#6      | +--------+
+--------+ |        |
           |        |
           +--------+

(2) or does it have to be structured like:

container:
#1 div .red
#2 div .red
#3 div .green
#4 div .green
#5 div .green
#6 div .blue
#7 div .blue

for:

.red       .green     .blue
+--------+ +--------+ +--------+
|#1      | |#3      | |#6      |
|        | +--------+ |        |
+--------+ +--------+ |        |
+--------+ |#4      | |        |
|#2      | |        | +--------+
|        | +--------+ +--------+
|        | +--------+ |#7      |
|        | |#5      | +--------+
+--------+ |        |
           |        |
           +--------+

(3) Or even:

container for .red:
#1 div .red
#2 div .red
container for .green:
#3 div .green
#4 div .green
#5 div .green
container for .blue:
#6 div .blue
#7 div .blue

for:

.red           .green         .blue
+------------+ +------------+ +------------+
| +--------+ | | +--------+ | | +--------+ |
| |#1      | | | |#3      | | | |#6      | |
| |        | | | +--------+ | | |        | |
| +--------+ | | +--------+ | | |        | |
| +--------+ | | |#4      | | | |        | |
| |#2      | | | |        | | | +--------+ |
| |        | | | +--------+ | | +--------+ |
| |        | | | +--------+ | | |#7      | |
| |        | | | |#5      | | | +--------+ |
| +--------+ | | |        | | |            |
|            | | |        | | |            |
|            | | +--------+ | |            |
+------------+ +------------+ +------------+

How would CSS for the first (1) case look like, if possible?

Upvotes: 1

Views: 81

Answers (4)

vals
vals

Reputation: 64164

If you can give the container a definite height, you can solve it with flex-box, setting an order for the classes, and adding pseudo-elements to act as "breakers" to force the wrap:

Those psuedo would be invisibles in production; I have made one of them visible just for demo purposes

.container {
  width: 500px;
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  border: solid 1px red;
  height: 500px;
}

.container div {
  width: 28%;
  margin: 10px;
}

.container div:nth-child(odd) {
  height: 130px;
}

.container div:nth-child(even) {
  height: 80px;
}

.container:before {
  content: "";
  width: 6px;
  /* only for demo */
  background-color: gray;
  /* only for demo */
  height: 100%;
  order: 15;
}

.container:after {
  content: "";
  height: 100%;
  order: 25;
}

.red {
  order: 10;
  background-color: red;
}

.green {
  order: 20;
  background-color: green;
}

.blue {
  order: 30;
  background-color: blue;
}
<div class="container">
  <div class="red"></div>
  <div class="green"></div>
  <div class="green"></div>
  <div class="blue"></div>
  <div class="red"></div>
  <div class="green"></div>
  <div class="blue"></div>
</div>

Upvotes: 1

Brad
Brad

Reputation: 8668

Ok here is a solution that maybe answers the question better.

You have 3 columns each with an unknown number of items, each you click shuffle the items will order randomly. If you want this to happen when the page loads just remove the $('#shuffle').click(function() { and ending }); and delete the button

$('#shuffle').click(function() {
  $('#box_container .box').each(function() {
    var itemCount = $('.item', this).length;
    $('.item', this).each(function() {
      var order = Math.floor(Math.random() * itemCount) + 1;
      $(this).css('order', order);
    });
  });
});
#box_container {
  width: 100%;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: space-around;
}

.box {
  color: #ddd;
  text-align: center;
  flex-basis: 30%;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  align-items: center;
}

.item {
  background: rgba(255, 255, 255, 0.25);
  height: 50px;
  width: 80%;
  border: 1px solid black;
}

.red { background: red;}
.blue { background: blue;}
.green { background: green;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<button id="shuffle">Shuffle</button>
<div id="box_container">
  <div class="box red">
    <div class="item item1">1</div>
    <div class="item item2">2</div>
    <div class="item item3">3</div>
  </div>
  <div class="box blue">
    <div class="item item1">1</div>
    <div class="item item2">2</div>
    <div class="item item3">3</div>
  </div>
  <div class="box green">
    <div class="item item1">1</div>
    <div class="item item2">2</div>
    <div class="item item3">3</div>
  </div>
</div>

Upvotes: 0

user4759415
user4759415

Reputation:

If you're interested in attaining your second example where the heights are variable and things just slot in to fill the specified columns then have a look at this

http://codepen.io/hoonin_hooligan/pen/OXbGBP

.your-column-wrapper {
  overflow: hidden;
  -webkit-column-count: 3;
  -webkit-column-gap: 15px;
  -webkit-column-fill: auto;
  padding-left: 15px;
  padding-right: 15px;
  margin-top: 10px;
}

.your-column-content {
  background-color: #fff;
  margin-bottom: 15px;
 -webkit-column-break-inside: avoid;
  page-break-inside: avoid;
  break-inside: avoid;
}

This is something I built a while back that could be a good place to start or use for your use case.

Upvotes: 0

Brad
Brad

Reputation: 8668

You could use flex box for this. Just add the order property to the items:

e.g. box1 {order:5;} will put box 1 in 5th position.

.container {
  width: 100%;
  display: flex;
  flex-direction:row;
  flex-wrap: wrap;
  justify-content:space-around; 
}

.box {
  height: 200px;
  color: #fff;
  text-align: center;
  flex-basis:30%;
  margin-top:5px;
}
.box p {
  padding-top: 90px;
}
.red {
  background: red;
  order:4;
}

.blue {
  background: blue;
  order:3;
}

.green {
  background: green;
  order:5;
}

.orange {
  background: orange;
  order:6;
}

.pink {
  background: pink;
  order:2;
}

.purple {
  background: purple;
  order:1;
}
<div class="container">
  <div class="box red"><p>1</p></div>
  <div class="box blue"><p>2</p></div>
  <div class="box green"><p>3</p></div>
  <div class="box orange"><p>4</p></div>
  <div class="box pink"><p>5</p></div>
  <div class="box purple"><p>6</p></div>
</div>

Upvotes: 0

Related Questions