如何使用弹性盒重新排序div?

时间:2017-08-25 14:22:47

标签: javascript html css css3 flexbox

我正在尝试为我的DOM保留一个seo友好和语义结构,而不重复整个元素以在各种位置显示它们。

我的布局基于display: flex个项目。我尝试实现以下目标:

Preview of mobile and desktop layout

要了解的重要事项:

  • 我不想根据窗口宽度显示/隐藏div(以避免不必要的重复)
  • 没有div具有已知或固定的高度
  • 在桌面上,div应该是垂直居中的,而右列是构建一个标记组(行为就像一个div)
  • 布局需要至少支持IE11 +

是否只有css解决方案来实现这一目标?

如果没有,可以很容易地删除绿色div并使用javascript将其内容粘贴到粉红色的内容中。但我确实对性能感到担忧,并且"闪烁"使用它,虽然调整浏览器大小使其更复杂。我是否会让这种不必要的复杂化?

这是小提示,显示工作解决方案,但使用javascript

CODEPEN DEMO

1 个答案:

答案 0 :(得分:6)

一般情况下,您无法单独使用Flexbox执行此操作,但可能会根据每个特定情况进行折衷。

单独使用Flexbox,使用固定高度,您可以完成此操作



* {
  box-sizing: border-box;
}

body, html {
  margin: 0;
}

.flex {
  width: 90%;
  margin: 5vh auto;
  height: 90vh;
  background: rgba(0, 0, 0, 0.05);  
  display: flex;
  flex-flow: column wrap;
}
.flex div {
  flex: 1;
  width: 50%;
}
.flex div:nth-child(2) {
  order: -1;
}
.flex::before {
  content: '';
  height: 100%;
}

@media (max-width:768px) {
  .flex div {
    width: auto;
  }
  .flex::before {
    display: none;
  }
 .flex div:nth-child(2) {
    order: 0;
  }
}


/*  styling  */
.flex-child {
  color: white;
  font-size: 2em;
  font-weight: bold;
}
.flex-child:nth-child(1) {
  background: #e6007e;
}
.flex-child:nth-child(2) {
  background: #f4997c;
}
.flex-child:nth-child(3) {
  background: #86c06b;
}

<div class="flex">
  <div class="flex-child">
    <div>Top/Right</div>
  </div>
  <div class="flex-child">
    <div>Center/Left</div>
  </div>
  <div class="flex-child">
    <div>Bottom/Right</div>
  </div>
</div>
&#13;
&#13;
&#13;

在这种情况下,如果不允许固定高度,您可以将Flexbox与float结合使用。

使用Flexbox将其设置为移动设备,然后在标记中首先添加 center 项目,然后使用order将其移至 top 之间和底部

使用媒体查询,您只需将 flex容器设为块元素,然后使用float左侧放置在左侧和对了在右边。

&#13;
&#13;
* {
  box-sizing: border-box;
}

body, html {
  margin: 0;
}

.flex {
  max-width: 1024px;
  width: 90%;
  margin: 5vh auto;
  height: 90vh;
  background: rgba(0, 0, 0, 0.05);
  
  display: flex;
  flex-direction: column;
}

.flex-child {
  color: white;
  font-size: 2em;
  font-weight: bold;
  padding: 5%;
  flex-basis: 33.333%;

  display: flex;
  align-items: center;
}

.flex-child:nth-child(1) {
  background: #e6007e;
  order: 1;
}
.flex-child:nth-child(2) {
  background: #f4997c;
}
.flex-child:nth-child(3) {
  background: #86c06b;
  order: 2;
}

@media (min-width: 768px) {
  .flex {
    display: block;
  }
  .flex-child {
    width: 50%;
  }
  .flex-child:nth-child(1) {
    float: left;
    height: 100%;
  }
  .flex-child:nth-child(2),
  .flex-child:nth-child(3) {
    float: right;
    height: 50%;
  }
}
&#13;
<div class="flex">
  <div class="flex-child">
    <div>Center/Left</div>
  </div>
  <div class="flex-child">
    <div>Top/Right</div>
  </div>
  <div class="flex-child">
    <div>Bottom/Right</div>
  </div>
</div>
&#13;
&#13;
&#13;

更新

以下是另一个将Flexbox与position: absolute相结合的版本,该版本也在桌面模式中垂直居中

更新后,添加了一个脚本来控制所以绝对定位的元素不会比正确的项目更大,如果是这样,调整弹性容器的高度。

注意,该脚本绝不是优化的,只是在那里展示如何在某些情况下修复

&#13;
&#13;
(function() {

  window.addEventListener("resize", resizeThrottler, false);

  var fp = document.querySelector('.flex');
  var fi = fp.querySelector('.flex-child:nth-child(1)');
  var resizeTimeout;
  function resizeThrottler() {
    // ignore resize events as long as an actualResizeHandler execution is in the queue
    if ( !resizeTimeout ) {
      resizeTimeout = setTimeout(function() {
        resizeTimeout = null;
        actualResizeHandler();
     
       // The actualResizeHandler will execute at a rate of 15fps
       }, 66);
    }
  }

  function actualResizeHandler() {
    // handle the resize event
    if (fp.offsetHeight <= fi.offsetHeight) {
      fp.style.cssText = 'height: '+fi.offsetHeight+'px';
    } else {
      fp.style.cssText = 'height: auto';
    }
  }

  window.addEventListener('load', function() {
    actualResizeHandler();
  })
  
}());
&#13;
* {
  box-sizing: border-box;
}

body, html {
  margin: 0;
}

.flex {
  position: relative;
  max-width: 1024px;
  width: 90%;
  margin: 5vh auto;
  height: 90vh;
  background: rgba(0, 0, 0, 0.05);
  
  display: flex;
  flex-direction: column;
}

.flex-child {
  color: white;
  font-size: 2em;
  font-weight: bold;
  padding: 5%;
}

.flex-child:nth-child(1) {
  order: 1;
}
.flex-child:nth-child(3) {
  order: 2;
}

.flex-child:nth-child(1) div {
  background: #e6007e;
}
.flex-child:nth-child(2) div {
  background: #f4997c;
}
.flex-child:nth-child(3) div {
  background: #86c06b;
}

@media (min-width: 768px) {
  .flex {
    justify-content: center;
  }
  .flex-child {
    width: 50%;
  }
  .flex-child:nth-child(1) {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
  }
  .flex-child:nth-child(n+2) {
    margin-left: 50%;
  }
}
&#13;
<div class="flex">
  <div class="flex-child">
    <div>Center/Left<br>with more<br>content<br>than any<br>of the<br>other items<br>other items<br>other items<br>other items<br>other items</div>
  </div>
  <div class="flex-child">
    <div>Top/Right<br>with more<br>content</div>
  </div>
  <div class="flex-child">
    <div>Bottom/Right<br>with more</div>
  </div>
</div>
&#13;
&#13;
&#13;

使用脚本,我们也可以在元素之间重新排序/移动项目。

Stack snippet

您还可以将其与媒体查询结合使用,并使用它来对元素进行实际重新排序

&#13;
&#13;
$( document ).ready(function() {
  $(window).resize(function() {
    if ($( window ).width() < 600 ) {
      $(".one").insertBefore("#b");
    } else {
      $(".one").insertBefore(".two");
    }
  });
});
&#13;
.outer, #flex, #flex2 {
  display: flex;
  flex-direction: column;
}
#a {
  order: 4;
  background: #ccc;
}
#b {
  order: 1;
  background: #aaa;
}
#c {
  order: 3;
  background: #d33;
}
.one {
  order: 2;
  background: #aaa;
}
.two {
  order: 5;
  background: #aaa;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="outer">
  <div id="flex">
    <div id="a">A</div>
    <div id="b">B</div>
    <div id="c">C</div>
  </div>

  <div id="flex2">
    <div class="one">Show me 2nd</div>
    <div class="two">Show me 5th</div>
  </div>

</div>
&#13;
&#13;
&#13;

更新2(已解答at another question,但稍后移至此处)

如果我们谈论较小的项目,如标题或较小的菜单,可以做许多网站平台提供商喜欢的&#34; squarespace&#34;,&#34; weebly&#34;,&#34; wordpress&# 34;等等。他们的模板包含不同的标记结构,其中一个项目有时存在两次,一个可用于桌面,另一个用于移动。

此外,如此小,在性能方面会有更少的成果(而且我个人不会再看到这个问题,而不是重复的CSS规则,每个屏幕尺寸一个,并且很乐意这样做而不是引入脚本)。

Fiddle demo

Stack snippet

&#13;
&#13;
.container {
  display: flex;
}
.container > div {
  width: 50%;
}
.container div:nth-child(-n+2) {
  border: dashed;
  padding: 10px;
}
.container > div:nth-child(1) {
  display: none;                                  /*  hide outer "Flower"  */
}

@media (max-width:768px) {
  .container {
    flex-direction: column;
  }
  .container div {
    width: auto;
  }
 .container div:nth-child(1) {
    display: block;                               /*  show outer "Flower"  */
  }
  .container div:nth-child(3) div:nth-child(1) {
    display: none;                                /*  hide inner "Flower"  */
  }
}
&#13;
<div class="container">
  <div>Flower</div>
  <div>Tree</div>
  <div>
    <div>Flower</div>
    <div>Bee</div>
  </div>
</div>
&#13;
&#13;
&#13;