Distribute elements of unequal height in two columns

≡放荡痞女 提交于 2019-12-12 18:23:06

问题


This is a development of this question with a crucial difference: elements to be distributed in two columns are of unequal heights. Please do not treat it as a duplicate.

WHAT I WANT TO ACHIEVE:

Given an unknown number of elements of roughly similar, but not identical height, the following should be achieved:

On desktop layout:

  • elements need to be distributed in two columns in the following manner:

    1 2

    3 4

    5 6

    etc

  • top element in the right column should be offset from the top border of the container at a greater distance than the top element of the left column, which should produce something like this:

  • distances between the elements in the same column should be the same

On mobile layout:

  • elements should remain in one column, positioned one below the other in their original order (1, 2, 3, 4, etc)

PROBLEM:

  • If I try to solve this by assigning display: inline-block to the elements, the browser will try to put each pair on a separate line; and every difference in their height will result in unequal spacing between the elements of the same column. Example:

function fillGrid() {
  const container = document.querySelector('.container');
  const times = [...new Array(10)];
  times.forEach((garbage, index) => {
    const element = document.createElement('div');
    element.innerText = index + 1
    element.classList.add('grid-element');
    container.appendChild(element);
  });
}

fillGrid()
* {
  box-sizing: border-box;
}

.container {
  width: 60%;
  margin: auto;
  background: papayawhip;
  padding-bottom: 60px;
}

@media screen and (max-width: 600px) {
  .container {
    display: block;
  }
  
  .grid-element {
    width: 100%;
  }
  
}

.grid-element {
  display: inline-block;
  width: 48%;
  height: 100px;
  background: green;
  vertical-align: middle;
  margin-bottom: 20px;
}

.grid-element:nth-child(2) {
  margin-top: 60px;
}

.grid-element:nth-child(odd) {
  margin-right: 10px;
}
.grid-element:nth-child(even) {
  grid-column: 2/3;
}

/* Just to add some disorder to grid element heights */

.grid-element:nth-child(6) {
  height: 150px;
}

.grid-element:nth-child(7) {
  height: 200px;
}
<div class="container"></div>
  • if I use CSS grid, the browser will create implicit rows for every new pair of elements, and the result will be visually similar to the previous attempt:

function fillGrid() {
  const container = document.querySelector('.container');
  const times = [...new Array(10)];
  times.forEach((garbage, index) => {
    const element = document.createElement('div');
    element.innerText = index + 1
    element.classList.add('grid-element');
    container.appendChild(element);
  });
}

fillGrid()
.container {
  display: grid;
  grid-template-column: 1fr 1fr;
  width: 60%;
  margin: auto;
  background: papayawhip;
  padding-bottom: 60px;
}

@media screen and (max-width: 600px) {
  .container {
    display: block;
  }
  
  .grid-element {
    width: 100%;
  }
  
  .grid-element:nth-child(2) {
    margin-top: 0;
  }
  
}

.grid-element {
  width: 90%;
  height: 100px;
  background: green;
  margin-bottom: 20px;
  font-size: 30px;
  font-weight: bold;
}

.grid-element:nth-child(2) {
  margin-top: 60px;
}

.grid-element:nth-child(odd) {
  grid-column: 1/2;
}
.grid-element:nth-child(even) {
  grid-column: 2/3;
}

/* Just to add some disorder to grid element heights */

.grid-element:nth-child(3) {
  height: 150px;
}

.grid-element:nth-child(6) {
  height: 150px;
}

.grid-element:nth-child(7) {
  height: 150px;
}
<div class="container"></div>
  • when I specify that I want all elements to go in the same row of CSS grid, they are positioned on top of one another (as discussed, without any solution, in this SO question)

This problem is, of course, trivially solved by placing the elements into two separate containers and then positioning these two containers relative to one another. The drawback with this approach is that in mobile layout, these containers will get stacked on top of one another, and the order of the elements will change (instead of 1 2 3 4 5 6 it will be, say, 1 3 5 2 4 6. I could, of course, draw two layouts on the same page and hide one of them depending on whether this is a desktop or a mobile screen, but I would rather not do so.

Is there a clean CSS-based solution to this problem?


回答1:


I don't think there's an elegant solution to this problem using only CSS. You're probably better off using a well-tested JavaScript library like Masonry to get this to work. It'll handle the responsive case you mentioned well, since the items will all be in a single container.

Here's a demo with a similar layout to the one you're describing: https://tympanus.net/Development/GridLoadingEffects/index.html



来源:https://stackoverflow.com/questions/53898032/distribute-elements-of-unequal-height-in-two-columns

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