响应地将2列布局折叠为单列

问题描述 投票:1回答:3

我目前有一个由内容框组成的页面,其布局使得有两个不等宽度的浮动列,每个框具有适合其内容的不同高度,如下所示:

.box {
  padding: 1em;
  border: 1px solid black;
  margin: 3px;
}

.left.col {
  float: left;
  width: 70%;
}

.right.col {
  float: right;
  width: 30%;
}

.b1 {
  background-color: red;
  height: 150px;
}

.b2 {
  background-color: green;
  height: 80px;
}

.b3 {
  background-color: blue;
  height: 80px;
}

.b4 {
  background-color: yellow;
  height: 40px;
}

.b5 {
  background-color: purple;
  height: 30px;
}

.b6 {
  background-color: cyan;
  height: 40px;
}

.b7 {
  background-color: orange;
  height: 40px;
}
<div class="boxes">
  <div class="left col">
    <div class="box b1">1</div>
    <div class="box b2">2</div>
    <div class="box b3">3</div>
  </div>
  <div class="right col">
    <div class="box b4">4</div>
    <div class="box b5">5</div>
    <div class="box b6">6</div>
    <div class="box b7">7</div>
  </div>
</div>

我希望能够响应性地将较小屏幕上的布局折叠成单个列,但这样我才能控制内容框的排序。为此,我很高兴将flexbox order与适当的polyfill一起用于不受支持的浏览器,例如flexibility。像这样的东西:

/* @media screen and (max-width: 570px) */
.boxes {
  display: flex;
  flex-direction: column;
}

.box {
  padding: 1em;
  border: 1px solid black;
  margin: 3px;
}

.b1 {
  background-color: red;
  height: 150px;
  order: 1
}

.b2 {
  background-color: green;
  height: 80px;
  order: 3
}

.b3 {
  background-color: blue;
  height: 80px;
  order: 5
}

.b4 {
  background-color: yellow;
  height: 40px;
  order: 2;
}

.b5 {
  background-color: purple;
  height: 30px;
  order: 4
}

.b6 {
  background-color: cyan;
  height: 40px;
  order: 6
}

.b7 {
  background-color: orange;
  height: 40px;
  order: 7
}
<div class="boxes">
  <div class="box b1">1</div>
  <div class="box b2">2</div>
  <div class="box b3">3</div>
  <div class="box b4">4</div>
  <div class="box b5">5</div>
  <div class="box b6">6</div>
  <div class="box b7">7</div>
</div>

到目前为止,我还没有做到的是将其作为一种单一的,响应迅速的方法来实现。我想我需要摆脱<div class="col">以便用flex控制盒子顺序,但似乎无法实现与flexbox和没有float的相同的2列布局。

是否有单一(CSS)解决方案,可以实现和响应切换两种布局?

编辑

IE9和Android 4.x都占我过去一年当前受众的2%左右,所以我仍然需要支持它们。因此,任何使用现代CSS技术(例如Flexbox,CSS网格)的解决方案都需要使用polyfill进行备份或优雅地回退/降级。

html css flexbox css-grid css-multicolumn-layout
3个回答
1
投票

由于唯一的纯CSS解决方案是CSS Grid,并且考虑到您需要支持i.a. IE9,您还需要一个脚本/后备来完成此任务。

由于Flexbox无法做得很好,动态(需要固定高度或脚本),绝对最简单和最容易维护的解决方案是保留包装器,只需用简单的脚本来回移动元素。

结合脚本为body添加一个类,我们可以使用CSS来控制元素。

注1;为了使其更加动态,可以优化脚本并利用例如元素的一个set属性,它应该放在哪里,虽然我没有在这里走得那么远。

笔记2;该脚本基于方向切换布局,但可以更新为使用宽度。

注3; resize事件使用了一个限制器,我最初是found at MDN,以避免昂贵的操作,如DOM修改。

堆栈代码段

(function(d, timeout) {

  function resizing() {
    if (window.innerHeight < window.innerWidth) {
      if (!(d.body.classList.contains('landscape'))) {
        d.body.classList.add('landscape');
        var target = d.querySelector('.right.col');
        target.appendChild(d.querySelector('.b4'));
        target.appendChild(d.querySelector('.b5'));
        target.appendChild(d.querySelector('.b6'));
        target.appendChild(d.querySelector('.b7'));
      }
    } else {
      if (d.body.classList.contains('landscape')) {
        d.body.classList.remove('landscape')
        var target = d.querySelector('.left.col');
        target.insertBefore(d.querySelector('.b4'), d.querySelector('.b2'))
        target.insertBefore(d.querySelector('.b5'), d.querySelector('.b3'))
        target.appendChild(d.querySelector('.b6'));
        target.appendChild(d.querySelector('.b7'));
      }
    }
  }

  /* event handlers */
  window.addEventListener("load", function() {
    resizing();
  }, false);

  window.addEventListener("resize", function() {
    if (!timeout) {
      timeout = setTimeout(function() {
        timeout = null;
        resizing();
      }, 66);
    }
  }, false);

}(document));
.box {
  padding: 1em;
  border: 1px solid black;
  margin: 3px;
}

.left.col {
  float: left;
  width: 100%;
}
.landscape .left.col {          /*  added rule  */
  width: 70%;
}

.right.col {
  float: right;
  width: 30%;
}

.b1 {
  background-color: red;
  height: 150px;
}

.b2 {
  background-color: green;
  height: 80px;
}

.b3 {
  background-color: blue;
  height: 80px;
}

.b4 {
  background-color: yellow;
  height: 40px;
}

.b5 {
  background-color: purple;
  height: 30px;
}

.b6 {
  background-color: cyan;
  height: 40px;
}

.b7 {
  background-color: orange;
  height: 40px;
}
<div class="boxes">
  <div class="left col">
    <div class="box b1">1</div>
    <div class="box b2">2</div>
    <div class="box b3">3</div>
  </div>
  <div class="right col">
    <div class="box b4">4</div>
    <div class="box b5">5</div>
    <div class="box b6">6</div>
    <div class="box b7">7</div>
  </div>
</div>

3
投票

如果你只能使用flexbox,那么使用nested containers or a height or max-height on the container布局很简单。

这种布局最有效的CSS解决方案将使用网格技术。

下面的解决方案是完整的和browser support is quite strong

jsFiddle demo

.boxes {
  display: grid;
  grid-template-columns: 3fr 1fr;
  grid-auto-rows: 10px;
  grid-gap: 5px;
  grid-template-areas:
   " red yellow"
   " red yellow"
   " red yellow"
   " red yellow"
   " red yellow"
   " red yellow"   
   " red purple"
   " red purple"
   " red purple"
   " red purple"
   " red purple"   
   " red cyan"
   " red cyan"
   " red cyan"
   " red cyan"
   " green cyan"
   " green orange "
   " green orange "
   " green orange "
   " green orange "
   " green orange "   
   " green . " 
   " green . " 
   " green . " 
   " blue . " 
   " blue . "  
   " blue . "    
   " blue . "  
   " blue . "  
   " blue . "  
   " blue . "   
   " blue . "     
}

.b1 { grid-area: red;    background-color: red;    }
.b2 { grid-area: green;  background-color: green;  }
.b3 { grid-area: blue;   background-color: blue;   }
.b4 { grid-area: yellow; background-color: yellow; }
.b5 { grid-area: purple; background-color: purple; }
.b6 { grid-area: cyan;   background-color: cyan;   }
.b7 { grid-area: orange; background-color: orange; }

.box {
  padding: 1em;
  border: 1px solid black;
}

@media (max-width: 570px) {
  .boxes { grid-template-columns: 1fr;
           grid-template-areas: 
   " red "
   " red "
   " red "
   " red "
   " red "
   " red "
   " red "
   " red "
   " red "
   " red "
   " red "   
   " red "
   " red "
   " red "
   " red "
   " yellow "
   " yellow "
   " yellow "
   " yellow "
   " yellow "
   " yellow "
   " green "
   " green "
   " green "
   " green "
   " green "
   " green "   
   " green " 
   " green " 
   " green " 
   " purple "
   " purple "
   " purple "
   " purple "
   " purple "
   " blue " 
   " blue "  
   " blue "    
   " blue "  
   " blue "  
   " blue "  
   " blue "   
   " blue "     
   " cyan "
   " cyan "
   " cyan "
   " cyan "
   " cyan "
   " orange "
   " orange "
   " orange "
   " orange "
   " orange " ;}

}
<div class="boxes">
  <div class="box b1">1</div>
  <div class="box b2">2</div>
  <div class="box b3">3</div>
  <div class="box b4">4</div>
  <div class="box b5">5</div>
  <div class="box b6">6</div>
  <div class="box b7">7</div>
</div>

特征:

  • 现代CSS3技术
  • 一个有两列的容器(3fr1fr)(more about the fr unit
  • 根据需要自动创建行;每排高10px ......
  • 所以跨越四行的网格区域是40px(加上任何grid-row-gap
  • 网格区域使用grid-template-areas属性中的字符串值进行布局
  • 网格区域可以使用其他方法(例如line-based placement)进行布局

0
投票

嵌套flexbox似乎工作,但我不确定在这个SO嵌入式HTML引擎中调试响应模式。看起来像下面的东西应该这样做。基本上3个flexbox,其中外部flexbox在行和列/ 100%宽度之间切换...

.boxes{
display:flex;

justify-content:center;
align-content:center;
align-items:center;
}

.col{
display:flex;
flex-flow: column nowrap;
justify-content:center;
align-content:center;
align-items:center;
}

.left{
flex: 0 1 auto;
min-width: 70%;
}
.right{
flex: 0 1 auto;
align-self:flex-start;
min-width: 30%;
}

.box{
flex: 0 1 auto;
min-width:100%
}


.b1{ background-color: red; height: 150px;}
.b2{ background-color: green; height: 80px;}
.b3{ background-color: blue; height: 80px;}
.b4{ background-color: yellow; height: 40px;}
.b5{ background-color: purple; height: 30px;}
.b6{ background-color: cyan; height: 40px;}
.b7{ background-color: orange; height: 40px;}

@media screen (max-width: 639px) {
.boxes{
flex-flow: column nowrap;
}
.left{
min-width: 100%;
}
.right{
min-width: 100%;
}
}
@media screen (min-width: 640px) {
.boxes{
flex-flow: row nowrap;
}
}
   
<div class="boxes">
<div class="left col">
    <div class="box b1">1</div>
    <div class="box b2">2</div>
    <div class="box b3">3</div>
</div>
<div class="right col">
    <div class="box b4">4</div>
    <div class="box b5">5</div>
    <div class="box b6">6</div>
    <div class="box b7">7</div>
</div>
</div>
© www.soinside.com 2019 - 2024. All rights reserved.