Two-column layout with ability to reorder items without JavaScript

和自甴很熟 提交于 2019-12-07 05:30:13

问题


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)

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/


回答1:


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



回答2:


You 2 column layout should also made using flex.

The only real problem is forcing a wrap at the point that you want it to be.

The best approach is where you can set a definite height to the container. In this case, forcing the wrap can be done with a pseudo element:

* {
  box-sizing: border-box;
}
div {
  width: 100%;
  height: 100px;
  border: 1px solid white;
}
.container {
  display: flex;
  flex-direction: column;
  height: auto;
  margin-top: 5px;
}
.col1 {
  width: 60%;
  background-color: red;
  height:300px;
}
.col2 {
  width: 40%;
  background-color: blue;
}
.one-column > div {
  width: 100%;
}
.two-column {
    flex-wrap: wrap;
    max-height: 800px;
}
.two-column:after {
    content: "";
    width: 10px;
    height: 10px;
    background-color: yellow;
    order: 2;
    margin-top: 1000px;
}
.two-column .col1 {
    order: 1;
}
.two-column .col2 {
    order: 3;
}
<div class="container two-column">
  <div class="col1">
    ONE
  </div>
  <div class="col2">
    TWO
  </div>
  <div class="col1">
    THREE
  </div>  
  <div class="col2">
    FOUR
  </div>
</div>
<div class="container one-column">
  <div class="col1">
    ONE
  </div>
  <div class="col2">
    TWO
  </div>
  <div class="col1">
    THREE
  </div>  
  <div class="col2">
    FOUR
  </div>
</div>


来源:https://stackoverflow.com/questions/48968515/two-column-layout-with-ability-to-reorder-items-without-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!