Problems building a flexbox grid

杀马特。学长 韩版系。学妹 提交于 2019-12-12 04:01:58

问题


I'm trying to build myself a flexbox with the following design:

My html looks like this (and I would like to NOT change this):

<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>

This is the standard layout of the joomla contact page. I want to change the design though without altering html/php code.

Is that possible using flexbox?

And can I use @media queries to make right_1 - right_4 to move under left on mobile view (< 800px or example)?

I myself cannot get it to work, I always end up with right_1 - right_4 next to each other instead of them stacking to the total height of the left portion.


回答1:


The layout you want cannot be achieved with flexbox. The reasons are explained here:

  • Is it possible for flex items to align tightly to the items above them?

However, the layout is relatively simple with CSS Grid.

There are, in fact, multiple methods for building the layout with Grid. I'll use the grid-template-areas property, which allows you to lay out your elements using ASCII art.

.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

In essence, here's how it works:

  1. We establish a block-level grid with display: grid.
  2. With grid-template-columns: 1fr 1fr we are telling the grid to create two columns. The fr unit tells the container to consume available space. It's similar to flexbox's flex-grow property. So both columns will share the full width of the container.
  3. The grid-template-areas property allows you to lay out named grid areas (that you have defined) to create a visual representation of your layout using ASCII art.
  4. In the media query for smaller screens, we remove one column and re-order the grid areas.

Browser Support for CSS Grid

  • Chrome - full support as of March 8, 2017 (version 57)
  • Firefox - full support as of March 6, 2017 (version 52)
  • Safari - full support as of March 26, 2017 (version 10.1)
  • Edge - full support as of October 16, 2017 (version 16)
  • IE11 - no support for current spec; supports obsolete version

Here's the complete picture: http://caniuse.com/#search=grid




回答2:


Here is one way to solve that, based on the existing markup and CSS Flexbox.

The left needs to be absolute positioned for desktop view and the page-header need a fixed height.

If you don't want to set a fixed height, you'll need a script that takes care of the height calculation

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>



回答3:


Probably the easiest way to change the order of div elements, you can use Jquery for this purpose. For example:

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

Eventually:

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>

It should work.



来源:https://stackoverflow.com/questions/44051482/problems-building-a-flexbox-grid

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!