Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Two-column layout with ability to reorder items without JavaScript

Is there a way to get 2 column layout that is transformed to a 1 column layout with a media query?

Conditions for 2 column layout:

  1. items should flow one after another within columns
  2. items within columns will have different heights
  3. item position (order) can be imposed by html markup element position

Conditions for 1 column layout:

  1. items should flow one after another
  2. items within columns will have different heights
  3. item position (!) cannot be imposed by html markup (should be controlled over css)

layout visualization

I have been considering two separate containers for columns - but that construct blocks me for reordering (mix) elements between columns when layout becomes 1 column. I seems that all elements should be placed within one container - then for 1 column layout flex can be used for reordering, but how to achieve 2 column layout in that case?

To simulate media query behaviour remove class "one-column" from main container.

<div id="container" class="one-column"> -> <div id="container" class="">

In this concept the main problem is that items within columns (2 column layout) are not flowing directly one after another (there are gaps between items in the right column).

Here's what I achieved so far:

* {
  box-sizing: border-box;
}
div {
  width: 100%;
  height: 100px;
  float: left;
}
#container.one-column {
  display: flex;
  flex-direction: column;
  height: auto;
}
#container {
  display: block;
}
.col1 {
  width: 60%;
  background-color: red;
  height:300px;
  float: left;
}
.col2 {
  width: 40%;
  background-color: blue;
  border: 1px solid white;
  float: right;
}
.one-column > div {
  width: 100%;
}
<div id="container" class="one-column">
  <div class="col1" style="order:2;">
    ONE
  </div>
  <div class="col2" style="order:1;">
    TWO
  </div>
  <div class="col1" style="order:4;">
    THREE
  </div>  
  <div class="col2" style="order:3;">
    FOUR
  </div>
</div>

JSFiddle: https://jsfiddle.net/3b6htt1d/40/

like image 205
IT Man Avatar asked Feb 24 '18 22:02

IT Man


1 Answers

Conditions for 2 column layout:

  1. items should flow one after another within columns
  2. items within columns will have different heights
  3. item position (order) can be imposed by html markup element position

That is exactly what CSS Columns does.

Conditions for 1 column layout:

  1. items should flow one after another
  2. items within columns will have different heights
  3. item position (!) cannot be imposed by html markup (should be controlled over css)

That is exactly what one can do with Flexbox and column direction.


So if one combine the two, for 2 columns they will, as shown in the left image sample, flow from top to bottom, and for 1 columns, you can control their position with order.

With this you avoid fixed heights and get dynamic/flexible sized items.

Updated fiddle

Stack snippet

* {
  box-sizing: border-box;
}
div {
  width: 100%;
  height: 100px;
}
#container.one-column {
  display: flex;
  flex-direction: column;
  height: auto;
}
.col1 {
  width: 60%;
  background-color: red;
  height:300px;
}
.col2 {
  width: 40%;
  background-color: blue;
  border: 1px solid white;
}
.one-column > div {
  width: 100%;
}

@media (min-width: 500px) {
  #container.one-column {
    display: block;
    columns: 2;
  }
  #container.one-column > div {
    -webkit-column-break-inside: avoid;
    page-break-inside: avoid;
    break-inside: avoid;
  }
  .zcol1 ~ .col1 {
    background-color: yellow;
    height:100px;
  }
}
<div id="container" class="one-column">
  <div class="col1" style="order:2;">
    ONE
  </div>
  <div class="col2" style="order:1;">
    TWO
  </div>
  <div class="col1" style="order:4;">
    THREE
  </div>  
  <div class="col2" style="order:3;">
    FOUR
  </div>
</div>

Here is another answer of mine, that might be another option, combining Flexbox with float.

  • Prevent next row taking up height of tallest item in previous row with flexbox?

Updated based on a comment

Here is a version combining Flexbox and float, which produce the layout your screen shot shows:

  • Updated demo
like image 136
Asons Avatar answered Oct 04 '22 04:10

Asons