响应式两列布局重新排序块

Responsive two column layout reordering the blocks

在移动布局中,我有六个 div,按重要性依次排列。在桌面上,我想重新排序项目。在下图中,左侧是移动布局,右侧是桌面布局。

六项的高度互不相关。布局应适用于任何高度。

我尝试了不同的解决方案。实现桌面布局的最简单方法是创建两个包装 div。但这不允许在移动设备上有不同的顺序。

我试着适应 to vertical. This answer for column breaks 几乎成功了,但它需要容器的固定高度。

我搜索了 girds,不幸的是,

有没有办法不用 Javascript 就可以解决这个问题? (我们目前的解决方案涉及 Javascript,但访问者可以注意到 div 的重新排列)。

  • flex 需要一个高度来换行,(请参阅最后一个片段演示,使用 javascript 设置所需的高度)

  • grid需要设置spanning来拼接元素,

  • columnCSS没看懂order...

...也许这里还剩下float

// set a random min-height on children 
for(let e of document.getElementsByClassName('element')) {
  e.style.minHeight = Math.floor(25 + Math.random() * 72) + 'px';
}
* {
  margin: 0;
  box-sizing: border-box;
}

/* reset breakpoint to your own value */
@media screen and (min-width: 568px) {
  div {
    width: 50%;
  }
  div:nth-child(odd) {
    float: left;
    clear: left;
  }
  div:nth-child(even) {
    overflow: hidden;
  }
}

/* demo purpose */
section {
  counter-reset: div;
}
div:before {
  counter-increment: div;
  content: "Div N°"counter(div);
}
div {
  border: solid;
  display:flex;
  align-items:center;
  justify-content:center;
}
<section>
  <div class="element"></div>
  <div class="element"></div>
  <div class="element"></div>
  <div class="element"></div>
  <div class="element"></div>
  <div class="element"></div>
  <div class="element"></div>
</section>

即便如此,元素之间仍会出现空隙,当跟随非浮动元素时,浮动始终会换行。


masonry 脚本可以作为一个选项,或者 javascript 来整理高度,因此 flex column 可以在顺序之外使用。

这里是 javascript 想法:

hl = 0;
hr = 0;
nb = 0;
for (let e of document.getElementsByClassName("element")) {
  nb++;
  h = Math.floor(50 + Math.random() * 50);
  e.style.height = h + "px";
  if (nb % 2 === 0) {
    hr = hr + h;
  } else {
    hl = hl + h;
  }
  if (hl > hr) {
    document.getElementById("test").style.height = hl + "px";
  } else {
    document.getElementById("test").style.height = hr + "px";
  }
}
* {
  margin:0;
  box-sizing:border-box;
}
div {border:solid;box-sizing:border-box;width:25%;background:tomato;}
/* demo purpose */
section {
  counter-reset: div;
  background:gray;
  display:flex;
  flex-direction:column ;
  flex-wrap:wrap;
}
div:nth-child(even) {
  order:2;
  width:75%;
  background:orange
}
div:before {
  display:block;
  counter-increment: div;
  content: "Div N°"counter(div);
}
@media screen and (max-width:568px) {
  section {
    height:auto!important;/* because of js script */
    display:block;
  }
  section div:nth-child(1n) {width:auto;}
}
<section id="test">
  <div class="element"></div>
  <div class="element"></div>
  <div class="element"></div>
  <div class="element"></div>
  <div class="element"></div>
  <div class="element"></div>
</section>

结果

我用 CSS 网格来解决这个问题。

HTML

<div class="list">
  <div class="item one">1</div>
  <div class="item two">2</div>
  <div class="item three">3</div>
  <div class="item four">4</div>
  <div class="item five">5</div>
  <div class="item six">6</div>
</div>

CSS

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: 'Verdana';
    color: #fff;
}


.list {
  background: gold;
  display: grid;
  grid-gap: 10px;
  text-align: center;

  grid-template-columns: repeat(1, 1fr);
  grid-auto-rows: minmax(70px, auto);
  grid-template-areas: 
        "one"
        "two"
        "three"
        "three"
        "four"
        "five"
        "six";

}

.item {
  background: gray
}

.one {
    grid-area: one;
}

.two {
    grid-area: two;
}

.three {
    grid-area: three;
}

.four {
    grid-area: four;
}

.five {
    grid-area: five;
}

.six {
    grid-area: six;
}


@media screen and (min-width: 650px) {
    .list {
      grid-template-columns: repeat(2, 1fr);
      grid-template-areas: 
        "one   two"
        "one   two"
        "one   four"
        "three four"
        "three six"
        "three six"
        "three six"
        "five  six"
        "five  .";
    }
}

@Paulie_D 的评论和@G-Cyr 的回答启发了我这个解决方案:

必须对齐的六个 div 分组在中间的两个 <div> 中,代表桌面布局中的两列。它们是容器的grand-children,而不是children。

在移动设备上,我们使用 display: contents; 忽略列 div,并使用 flexbox 的 order: n; 重新排序 grand-children。在桌面上,我们使用 display: inline-block; 显示两列,并在 source-order 中保留 grand-children。

for(let e of document.getElementsByClassName('item')) {
  e.style.minHeight = Math.floor(25 + Math.random() * 72) + 'px';
}
.container {
  display: flex;
  flex-direction: column;
}
.item {
  margin-bottom: 0.5em;
  text-align: center;
  background:#ddd;
  padding: 1em;
}
.left, .right{
  display: contents;
}
.item1, .item2{
  order: 1;
}
.item3, .item4{
  order: 2;
}
.item5, .item6{
  order: 3;
}

@media (min-width: 40em){
  .left, .right{
    display: inline-block;
    vertical-align: top;
  }
  .container{
    display: block;
  }
  .left{
    width: calc(67% - 0.5em);
    margin-right: 0.5em;
  }
  .right{
    width: 33%;
  }
}
<div class="container">
  <div class="left">
    <div class="item item1">1</div>
    <div class="item item3">3</div>
    <div class="item item5">5</div>
  </div><div class="right">
    <div class="item item2">2</div>
    <div class="item item4">4</div>
    <div class="item item6">6</div>
  </div>
</div>