如何使用flexbox实现复杂的响应式HTML布局?

时间:2016-02-23 10:09:36

标签: html css layout responsive-design flexbox

我已经研究过Flexbox以实现响应式布局,如下图所示。不幸的是,我仍然没有想出如何实现如图1所示的桌面布局,它在小于414像素的视口上重新排列为图2。

图1(桌面视口)

Desktop version of the layout

图2(移动视口)

Mobile (less than 414px wide) version of the layout (缩放版)

点击此处查看image in original size

到目前为止我的代码:

.flexbox {
  display: -webkit-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  flex-wrap: wrap;
  width: 100%;
  margin: 0;
  flex-direction: row;
}
.content-flexbox.one {
  flex-basis: calc(66% - 1rem);
  order: 2;
}
.content-flexbox.two {
  flex-basis: calc(30% - 1rem);
  order: 1;
}
.content-flexbox.three {
  order: 3;
}
.content-flexbox.four {
  order: 4;
}
.content-flexbox {
  margin: 1rem;
  -webkit-box-flex: 1;
  -webkit-flex: 1;
  -ms-flex: 1;
  flex: 1;
}
@media only screen and (max-width: 959px) {
  .flexbox {
    -flex-direction: column;
    padding-top: 1rem;
  }
  .content-flexbox {
    margin: 1rem;
    flex: 1;
    flex-basis: 100%;
  }
  .content-flexbox.one {
    flex-basis: 100%;
    order: 1;
  }
  .content-flexbox.two {
    flex-basis: 100%;
    order: 2;
  }
}
<div class="flexbox">
  <div class="content-flexbox one">
    <h1 class="posttitle">Lorem ipsum</h1>
    <h2 class="subtitle">dolor sit amet</h2>
  </div>
  <div class="content-flexbox two">
    <img src="http://placehold.it/300x300" />
  </div>
  <div class="content-flexbox three">
    <span>Lorem ipsum dolor</span>
  </div>
  <div id="container-voting" class="content-flexbox four">
    <div class="inner-container set">
      <span>Lorem ipsum dolor</span>
    </div>
    <div class="inner-container get">
      <span>Lorem ipsum dolor</span>
    </div>
  </div>
</div>

我的问题

这对Flexbox来说是否可行?有更好的选择更适合这种布局吗?

5 个答案:

答案 0 :(得分:3)

虽然这个问题明确要求使用flexbox方法,但还有另一种方法可以实现使用简单浮动
媒体查询允许在小于414px宽的视口上按所需顺序重新排列元素:

&#13;
&#13;
.wrap {
  background: #d0d0d0;
  padding: 1%;
}
.wrap:after {
  content: '';
  display: block;
  clear: both;
}
.el {
  float: left;
  margin: 1%;
}
.el1 {
  width: 31.33%;
  padding-bottom: 31.33%;
  background: #FF7676;
}
.el2 {
  float: right;
  width: 64.66%;
  padding-bottom: 14.66%;
  background: #C2FF76;
}
.el3 {
  width: 31.33%;
  padding-bottom: 14.66%;
  background: #FF9BF7;
}
.el4 {
  width: 31.33%;
  padding-bottom: 6.33%;
  background: #9BA4FF;
}
@media (max-width: 414px) {
  .el2, .el4 {
    width: 98%;
    padding-bottom: 31.33%;
  }
  .el1, .el3 {
    width: 48%;
    padding-bottom: 48%;
  }
}
&#13;
<div class="wrap">
  <div class="el el2"></div>
  <div class="el el1"></div>
  <div class="el el3"></div>
  <div class="el el4"></div>
  <div class="el el4"></div>
</div>
&#13;
&#13;
&#13;

请注意,我使用padding-bottom来保持此示例中元素的宽高比(this answer中的更多信息)。
我不知道你打算在块中放入什么内容,但是如果你想坚持使用&#34;填充技术&#34;你将需要使用绝对位置。对于纯文本内容,您可以查看this fiddle

答案 1 :(得分:1)

您正在寻找实验网格语法。 Flexbox适用于较小的小部件或组件布局系统。网格用于整体页面布局,它很棒。

事实上,网格目前仅支持IE,Edge和即将推出的Safari浏览器,但据称Firefox和Chrome支持即将到来,您可以通过启用正确的开发者标志来开始尝试那些浏览器。

以下是一些示例代码,但同样,只有当您的浏览器支持新的网格语法时,它才会起作用。

*{
  box-sizing: border-box;
}

.flexbox{
  width: 320px;
  display: grid;
  grid-template-columns: calc(50% - 0.5ch) calc(50% - 0.5ch);
  grid-gap: 1ch;
}

.one{
  order: 2;
  background-color: red;
}

.two{
  grid-column: 1 / 3;
  order: 1;
  background-color: green;
}

.three{
  order: 3;
  background-color: pink;
}

.four{
  display: grid;
  grid-column: 1 / 3;
  grid-gap: 1ch;
  order: 4;
  background-color: lavender;
}

.inner-container{
  background-color: violet;
}

@media screen and (min-width: 500px){
  .flexbox{
    width: 500px;
    grid-template-columns: calc(33.333% - 0.333ch) calc(33.333% - 0.333ch) calc(33.333% - 0.333ch);
  }
  
  .one{
    grid-row: 1 / 3;
    order: 1;
  }
  
  .two{
    order: 2;
    grid-column: 2 / 4;
  }
  
  .three{
    order: 3;
  }
  
  .four{
    grid-column: 3 / 4;
    order: 4;
  }
}
<div class="flexbox">
<div class="content-flexbox one">
    <h1 class="posttitle">Lorem ipsum</h1>
    <h2 class="subtitle">dolor sit amet</h2>
</div>
<div class="content-flexbox two">
    <img src="http://placehold.it/300x300" />
</div>
<div class="content-flexbox three">
    <span>Lorem ipsum dolor</span>
</div>
<div id="container-voting" class="content-flexbox four">
    <div class="inner-container set">
        <span>Lorem ipsum dolor</span>
    </div>
    <div class="inner-container get">
        <span>Lorem ipsum dolor</span>
    </div>
</div>

答案 2 :(得分:1)

问题在于,如果您希望能够重新排列所有项目,则它们必须是同一个Flex容器的弹性项目。但Flexbox没有提供任何直接的方法来使元素占据多个弹性线。

但是,您可以使用多个容器和display: contents

  

元素本身不生成任何框,但它的子元素和   伪元素仍然正常生成框。出于...的目的   框生成和布局,必须将元素视为具有   已被文档中的子元素和伪元素替换   树。

/* Desktop */
.container {
  display: flex;
  flex-wrap: wrap;
}
.container > * {
  flex-grow: 1;
}
.item {
  margin: 2px;
}
.column {
  flex-direction: column;
}
.fill {
  width: 100%;
}
/* Mobile */
@media (max-width: 414px) {
  .container > .container {
    display: contents;
  }
  .i2 {
    order: -1;
  }
  .i4 {
    width: 100%;
  }
}
/* Pretty */
.i1 { background: #FF7676; }
.i2 { background: #C2FF76; }
.i3 { background: #FF9BF7; }
.i4 { background: #9BA4FF; }
<div class="container">
  <div class="item i1">1</div>
  <div class="container">
    <div class="item i2 fill">2</div>
    <div class="item i3">3</div>
    <div class="container column">
      <div class="item i4">4a</div>
      <div class="item i4">4b</div>
    </div>
  </div>
</div>

唯一的问题是display: contents尚未得到广泛支持,但您可以看到它在Firefox上运行。

答案 3 :(得分:0)

我认为这不可能与纯CSS一起使用,但您可以使用一些js并在使用wrapAll()unwrap()调整大小时更改html结构。当窗口为&lt;时,您还需要使用media queries来更改顺序和一些css。 414px。

&#13;
&#13;
$(window).on("resize", function() {
  var windowW = $(window).width();

  if (windowW < 414) {
    if ($('.right, right-inner').length) $('.two, .four').unwrap();
    if (!$('.top').length) $('.one, .two, .three').wrapAll('<div class="top"></div>');
  } else {
    if ($('.top').length) $('.one, .two, .three').unwrap();
    if (!$('.right, .right-inner').length) {
      $('.three, .four').wrapAll('<div class="right-inner"></div>');
      $('.two, .right-inner').wrapAll('<div class="right"></div>');
    }
  }
}).resize();
&#13;
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
body,
html {
  margin: 0;
  padding: 0;
  font-family: sans-serif;
}
.flexbox {
  display: flex;
  min-height: 100vh;
  color: white;
  font-size: 50px;
}
.one {
  flex: 1;
  background: #FF7676;
  margin: 10px;
}
.right {
  flex: 2;
  display: flex;
  flex-direction: column;
  margin: 10px;
}
.two {
  height: 40%;
  display: flex;
  margin-bottom: 20px;
  margin-right: 10px;
}
.two img {
  width: 100%;
  margin: 0;
}
.right-inner {
  display: flex;
  flex: 2;
}
.three,
.four {
  flex: 1;
}
.three {
  background: #FF9BF7;
  margin-right: 10px;
}
.four {
  display: flex;
  flex-direction: column;
}
.set,
.get {
  background: #9BA4FF;
  flex: 1;
  margin: 5px;
}
.set {
  margin-top: 0;
}
.get {
  margin-bottom: 0;
}
@media(max-width: 414px) {
  .flexbox {
    flex-direction: column;
  }
  .flexbox > * {
    flex: 1;
    margin: 10px;
  }
  .get,
  .set {
    margin: 0;
    margin-bottom: 10px;
  }
  .two {
    order: -1;
    flex: 0 0 100%;
    margin-bottom: 0;
  }
  .two img {
    height: 100px;
  }
  .one,
  .three {
    width: 50%;
    margin: 0;
  }
  .one {
    margin-right: 10px;
  }
  .top {
    display: flex;
    flex-wrap: wrap;
  }
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<div class="flexbox">
  <div class="content-flexbox one">
    <span class="posttitle">1</span>
  </div>
  <div class="right">
    <div class="content-flexbox two">
      <img src="http://placehold.it/300x300/C2FF76" />
    </div>

    <div class="right-inner">
      <div class="content-flexbox three">
        <span>3</span>
      </div>
      <div id="container-voting" class="content-flexbox four">
        <div class="inner-container set">
          <span>4a</span>
        </div>
        <div class="inner-container get">
          <span>4b</span>
        </div>
      </div>
    </div>
  </div>
</div>
&#13;
&#13;
&#13;

答案 4 :(得分:-1)

我发现在使用宽度为%的液体样式页面之前,您可以制作两个带浮动的容器,如上所述。如果您在aproche移动视口中使用媒体查询来声明断点。