【问题标题】:Problems building a flexbox grid构建 flexbox 网格的问题
【发布时间】:2017-05-18 15:07:29
【问题描述】:

我正在尝试使用以下设计为自己构建一个 flexbox:

我的 html 看起来像这样(我不想改变它):

<div class="wrapper">
  <div class="page-header">Heading</div>
  <h3 class="right_1">right_1</h3>
  <div class="right_2">right_2</div>
  <div class="left">form element</div>
  <h3 class="right_3">right_3</h3>
  <div class="right_4">right_4</div>
</div>

这是 joomla 联系页面的标准布局。我想在不更改 html/php 代码的情况下更改设计。

这可以使用 flexbox 吗?

我可以使用@media 查询使right_1 - right_4 在移动视图上移动到left 下吗(

我自己无法让它工作,我总是以right_1 - right_4 并排结束,而不是它们堆叠到左侧部分的总高度。

【问题讨论】:

  • 不,仅靠 flexbox 是不可能的。您将不得不尝试实验性的 CSS 网格。 flexbox 的作用是它为您提供了一种灵活分布元素的简单方法,但不是双轴的(就像您希望在网格中那样)。
  • 好的,谢谢你的信息。除了编辑 joomla 的 html/php 结构之外,我对任何其他内容都持开放态度。

标签: html css flexbox css-grid


【解决方案1】:

你想要的布局无法用 flexbox 实现。原因在这里解释:

但是,CSS Grid 的布局相对简单。

事实上,使用 Grid 构建布局有多种方法。我将使用 grid-template-areas 属性,它允许您使用 ASCII 艺术来布置元素。

.wrapper {
  display: grid;
  height: 100vh;
  grid-template-columns: 1fr 1fr;
  grid-template-areas: 
     " heading heading "
     "  left_ right1   "
     "  left_ right2   "
     "  left_ right3   "
     "  left_ right4   "
}

.page-header { grid-area: heading; }
.right_1     { grid-area: right1;  }
.right_2     { grid-area: right2;  }
.right_3     { grid-area: right3;  }
.right_4     { grid-area: right4;  }
.left        { grid-area: left_;   } /* "left" is a pre-defined CSS keyword,
                                         so it may not work */
@media ( max-width: 800px ) {
  .wrapper { 
     grid-template-columns: 1fr;
     grid-template-areas: 
        " heading "
        "  left_  "
        "  right1 "
        "  right2 "
        "  right3 "
        "  right4 "
     }
}

/* non-essential decorative styles */
.page-header { background-color: red; }
.right_1     { background-color: chartreuse; }
.right_2     { background-color: aqua; }
.right_3     { background-color: skyblue; }
.right_4     { background-color: black; color: white; }
.left        { background-color: cornsilk; }
body         { margin: 0; }
.wrapper > * {
  font-weight: bold;
  font-size: 1.5em;
  border: 1px solid black;
  margin: 0;
  display: flex;
  justify-content: center;
  align-items: center;
}
<div class="wrapper">
  <div class="page-header">Heading</div>
  <h3 class="right_1">right_1</h3>
  <div class="right_2">right_2</div>
  <div class="left">form element</div>
  <h3 class="right_3">right_3</h3>
  <div class="right_4">right_4</div>
</div>

jsFiddle demo

本质上,它是这样工作的:

  1. 我们使用display: grid 建立块级网格。
  2. 使用grid-template-columns: 1fr 1fr,我们告诉网格创建两列。 fr 单元告诉容器消耗可用空间。它类似于 flexbox 的 flex-grow 属性。因此,两列将共享容器的整个宽度。
  3. grid-template-areas 属性允许您对命名的网格区域(已定义)进行布局,以使用 ASCII 艺术创建布局的可视化表示。
  4. 在小屏幕的媒体查询中,我们删除一列并重新排列网格区域。

浏览器支持 CSS 网格

  • Chrome - 自 2017 年 3 月 8 日起提供全面支持(版本 57)
  • Firefox - 自 2017 年 3 月 6 日起提供全面支持(版本 52)
  • Safari - 自 2017 年 3 月 26 日起全面支持(版本 10.1)
  • Edge - 自 2017 年 10 月 16 日起提供全面支持(版本 16)
  • IE11 - 不支持当前规范;支持过时版本

这是完整的图片:http://caniuse.com/#search=grid

【讨论】:

  • 听起来不错,我会把代码扔进去检查一下;)
  • 我必须说效果很好。我唯一遗漏的是顶部.wrapper{..} 中的height: 100vh;,因为它导致&lt;div class="wrapper"&gt; 的内容溢出,这看起来很可怕,但只要摆脱height: 100vh; 就可以了;)现在只剩下一件事了是让它以某种方式在边缘/IE上工作(还没有尝试过)
  • 这就是为什么我首先选择了flexbox,它支持IE/Edge和opera mini/android浏览器。
  • 我现在正在做的另一件事是限制右边元素的大小。 right_1 & right_2right_3 & right_4 之间有很大的差距(1/3 是标题,3/4 是对应的文字)
  • @Alkahna 这是由h3 元素引起的,它具有默认边距。将它们的边距设置为 0,它将消失
【解决方案2】:

这是解决这个问题的一种方法,基于现有的标记和 CSS Flexbox。

left 需要绝对定位以用于桌面视图,page-header 需要固定高度。

如果您不想设置固定高度,则需要一个负责计算高度的脚本

html, body {
  margin: 0;
}
.wrapper {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
.wrapper * {
  padding: 0 10px;
  margin: 0;
  border: 1px solid black;
  box-sizing: border-box;  
}
.page-header {
  height: 70px;
  width: 100%;
  background: red;
}
.right_1, .right_2, .right_3, .right_4 {
  flex: 1;
  width: 50%;
  margin-left: 50%;
  background: lightblue;
}
.left {
  position: absolute;
  left: 0;
  top: 70px;
  width: 50%;
  min-height: calc(100vh - 70px);
  background: yellow;
}
@media only screen and (orientation: portrait) {
  .wrapper * {
    width: 100%;
    margin: 0;
  }
  .left {
    position: static;
    flex: 1;
    min-height: auto;
    order: -1
  }
  .page-header {
    order: -2;
  }
}
<div class="wrapper">
  <div class="page-header">Heading</div>
  <h3 class="right_1">right_1</h3>
  <div class="right_2">right_2</div>
  <div class="left">form element</div>
  <h3 class="right_3">right_3</h3>
  <div class="right_4">right_4</div>
</div>

【讨论】:

  • 我也测试了你的解决方案,发现媒体查询需要一些调整才能正常工作:.wrapper@media only screen and (max-width: 768px) { .wrapper * { width: 100% !important; margin: 0 !important; } .left { position: static !important; flex: 1; min-height: auto !important; order: -1 } } 内容溢出.wrapper,但我会继续解决这个问题跨度>
  • @Alkahna 当然可以,因为我没有进行任何此类调整。 CSS Grid 更好,因为您获得了响应更快的解决方案。它的缺点当然是浏览器支持。如果您打算使用 Flexbox,我建议您添加一个小脚本来处理 left 的定位/大小。我的意思是,这是一个不错的权衡,因为它不会在浏览器上增加太多工作量
  • @Alkahna 顺便说一句,如果您可以使用媒体查询控制大小,则当然不需要该脚本
  • 我注意到,由于我已经有其他媒体查询,我将继续使用它们并尽可能避免使用脚本。您对我的原始问题的编辑有什么想法吗?
  • @Alkahna 这是一个全新的问题,所以回滚编辑并根据您的新要求创建一个新问题。并在这里接受最能解决这个问题的那个。
【解决方案3】:

这可能是更改 div 元素顺序的最简单方法,您可以为此目的使用 Jquery。例如:

$("#element1").before($("#element2"));

最终:

CSS:

#blocks {
    display: box;
    box-orient: vertical;
}
#b1 {
    box-ordinal-group: 2;
}
#b2 {
    box-ordinal-group: 3;
}

HTML:

<div id="blocks">
    <div id="b1">Block 1</div>
    <div id="b2">Block 2</div>
    <div id="b3">Block 3</div>
</div>

它应该可以工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-24
    • 2023-02-09
    • 2021-06-29
    • 2019-10-03
    • 1970-01-01
    • 2019-01-09
    相关资源
    最近更新 更多