Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Layout possible? Flexbox vs Float layout with multiple columns and rows

Tags:

css

flexbox

I'm curious if this layout is possible with flexbox. I can't seem to work out divs 3 & 4 to fall under #2. This is pretty easy with floats, just curious if I'm missing some properties that may help with flexbox.

Layout

+-------+-------+-------+
| div 1 |     div 2     |
+       +-------+-------+
|       | div 3 | div 4 |
+-------+-------+-------+

Markup

<div class="features">
  <div class="feature feature-1">1</div>
  <div class="feature feature-2">2</div>
  <div class="feature feature-3">3</div>
  <div class="feature feature-4">4</div>
</div>

Demo

http://codepen.io/mikevoermans/pen/xbWvJJ?editors=110

like image 627
mikevoermans Avatar asked Feb 21 '15 16:02

mikevoermans


People also ask

What is the difference between a float layout and a flexbox layout?

Instead of using a float to create layouts by floating elements to the left or the right, flexbox allows you to create layouts by aligning items to a single axis. The axis can be horizontal or vertical. It is best used for distributing space for items in the same axis.

Which is better flexbox or float?

Using floats we are limited to place items left or right but using flexbox we can modify our models in all four directions. Flexbox is a new concept in CSS to achieve a responsive webpage with some important properties of flexbox. We should use flexbox over floats.

What are the main differences between flexbox and Grid layout?

The basic difference between CSS Grid Layout and CSS Flexbox Layout is that flexbox was designed for layout in one dimension - either a row or a column. Grid was designed for two-dimensional layout - rows, and columns at the same time.

How many types of layout models are in flexbox?

CSS Flexbox Layout Module Before the Flexbox Layout module, there were four layout modes: Block, for sections in a webpage. Inline, for text. Table, for two-dimensional table data.


2 Answers

Flexbox does not like flex items that expand through multiple columns or rows, because in fact flexbox has no grid notion.

However, using some tricks, you can achieve this layout (and more complicated ones too):

  • Use a row layout

    ┌─┬─┬─┬─┐
    │1│2│3│4│
    └─┴─┴─┴─┘
    
  • Allow line breaks with flex-wrap: wrap.

  • Use a pseudo element to force a line break after 2

    ┌─┬─┐
    │1│2│
    ├─┼─┤
    │3│4│
    └─┴─┘
    
  • Use flex: 1 on all flex items.

    ┌─────────┬─────────┐
    │1        │2        │
    ├─────────┼─────────┤
    │3        │4        │
    └─────────┴─────────┘
    
  • Set margin-left: 50% to 3

    ┌─────────┬─────────┐
    │1        │2        │
    └─────────┼────┬────┤
              │3   │4   │
              └────┴────┘
    
  • Set height: 200px, to 2, 3 and 4. Set height: 400px to 1.

    ┌─────────┬─────────┐
    │1        │2        │
    │         ├─────────┘
    │         │
    └─────────┼────┬────┐
              │3   │4   │
              └────┴────┘
    
  • Set margin-bottom: -200px to 1:

    ┌─────────┬─────────┐
    │1        │2        │
    │         ├────┬────┤
    │         │3   │4   │
    └─────────┴────┴────┘
    
  • Since you have borders, use box-sizing: border-box on all boxes to make height include the borders. Otherwise 1 would need height: 416px; margin-bottom: -216px.

  • Note flexbox introduces auto as the new initial value of min-width. That could allow the content to force some boxes to grow. That would break the layout, so disable it with min-width: 0 or setting overflow to anything but visible.

Here is the code:

.features {
  display: flex;
  flex-flow: row wrap;
}
.feature {
  background: #ccc;
  border: 8px solid #fff;
  height: 200px;
  box-sizing: border-box;
  min-width: 0;
  flex: 1;
}
.feature-1 {
  /* Make it taller without increasing the height of the flex line */
  height: 400px;
  margin-bottom: -200px;
}
.features:after {
  /* Force line break */
  content: '';
  width: 100%;
}
.feature-2 ~ .feature {
  /* Place 3 and 4 after the line break */
  order: 1;
}
.feature-3 {
  margin-left: 50%;
}
<div class="features">
  <div class="feature feature-1">1</div>
  <div class="feature feature-2">2</div>
  <div class="feature feature-3">3</div>
  <div class="feature feature-4">4</div>
</div>

However, it would be easier to modify the HTML in order to have nested flexboxes.

#wrapper {
  height: 400px;
}
.flex {
  display: flex;
}
.column {
  flex-direction: column;
}
.flex > div {
  min-width: 0;
  flex: 1;
}
.item {
  background: #ccc;
  border: 8px solid #fff;
}
<div id="wrapper" class="flex row">
  <div class="item">1</div>
  <div class="flex column">
    <div class="item">2</div>
    <div class="flex row">
      <div class="item">3</div>
      <div class="item">4</div>
    </div>
  </div>
</div>
like image 136
Oriol Avatar answered Oct 06 '22 01:10

Oriol


Not possible with flexbox, but possible with CSS Grid. It's not yet shipped with all major browsers, but there's a polyfill:

https://jsfiddle.net/hvdq63ah/

.features {
    display: grid;
    grid-template-areas:
      "feature1 feature2 feature2"
      "feature1 feature3 feature4";
    grid-template-columns: auto minmax(min-content, 1fr) minmax(min-content, 1fr);
    grid-template-rows: auto minmax(min-content, 1fr);      
      
		background-color: #fff;
}

.feature-1    { grid-area: feature1 }
.feature-2    { grid-area: feature2 }
.feature-3    { grid-area: feature3 }
.feature-4    { grid-area: feature4 }

.feature {
  border: 1px solid black;
  padding: 20px;
}
<div class="features">
  <div class="feature feature-1">1</div>
  <div class="feature feature-2">2</div>
  <div class="feature feature-3">3</div>
  <div class="feature feature-4">4</div>
</div>
like image 31
Vanuan Avatar answered Oct 06 '22 00:10

Vanuan