4

Can I make this flex-box direction using 1 flex container and 4 flex items

-----  ----- -----
| 1 |  |   | |   |
-----  | 3 | | 4 |
-----  |   | |   |
| 2 |  |   | |   |
-----  ----- -----
nwellnhof
  • 32,319
  • 7
  • 89
  • 113
hafizgik
  • 77
  • 1
  • 2
  • 7
  • Related: [Have certain items stack along the cross axis within a row/column of a flex layout with only CSS](http://stackoverflow.com/q/30489151/1529630) – Oriol Aug 08 '15 at 23:03
  • Related: [Flexbox 3 divs, two columns, one with two rows](https://stackoverflow.com/questions/43056180/flexbox-3-divs-two-columns-one-with-two-rows) – TylerH Jun 16 '20 at 17:43
  • Also Related (and revealing; flexbox is one-directional. If you want two directions, use CSS Grids): [Unequal row heights in a flex column](https://stackoverflow.com/questions/62348117/unequal-row-heights-in-a-flex-column) – TylerH Jun 16 '20 at 17:43

2 Answers2

3

Using a container around 1 and 2 you can do it, like this:

* {
    box-sizing: border-box;
}
.wrapper {
    display: flex;
    flex-direction: row;
}
.container {
    flex-direction: column;
    flex-grow: 1;
}
.item  {
    background: tomato;
    color: white;
    font-weight: bold;
    font-size: 3em;
    text-align: center;
    flex-grow: 1;
    border: 1px solid black;
}
.inner {
    height: 100px;
    line-height: 100px;
}
.outer {
    height: 200px;
    line-height: 200px;
}
<div class="wrapper">
    <div class="container">
        <div class="item inner">1</div>
        <div class="item inner">2</div>
    </div>
    <div class="item outer">3</div>
    <div class="item outer">4</div>
</div>

But if you don't want to use a container for 1 and 2 I'm afraid you can not do it, because the direction of the children is determined by the parent.

.container {
   flex-direction: row | row-reverse | column | column-reverse;
}

Your best shot is to use the property align-self, this allows the default alignment (or the one specified by align-items) to be overridden for individual flex items. like this:

* {
    box-sizing: border-box;
}
.wrapper {
    display: flex;
    flex-direction: row;
}
.item  {
    background: tomato;
    color: white;
    font-weight: bold;
    font-size: 3em;
    text-align: center;
    flex-grow: 1;
    border: 1px solid black;
}
.inner {
    height: 100px;
    line-height: 100px;
}
.outer {
    height: 200px;
    line-height: 200px;
}

.item-top{
    align-self: flex-start;
}
.item-bottom{
    align-self: flex-end;
}
<div class="wrapper">
    <div class="item inner item-top">1</div>
    <div class="item inner item-bottom">2</div>
    <div class="item outer">3</div>
    <div class="item outer">4</div>
</div>

But note that float, clear and vertical-align have no effect on a flex item.

Check this out for a better understanding of flex box.

monastic-panic
  • 3,987
  • 1
  • 22
  • 20
Yandy_Viera
  • 4,320
  • 4
  • 21
  • 42
  • Thank you @Yandy_Viera , now I know it's impossible. Anyway, did you know how to reorder this flex items in **media queries** using `order:` ? – hafizgik Aug 07 '15 at 09:40
  • By default, flex items are laid out in the source order. However, the `order` property controls the order in which they appear in the flex container, e.g if you set `order: 10` to item 3 it will appears in the last. Anyway I recommend you that post another question with your html markup and with img of what you want to achieve before and after applying the **media queries** and we will help you. – Yandy_Viera Aug 07 '15 at 13:24
2

As opposed to the accepted answer, this layout is achievable without using a wrapper container, though this solution requires a fixed height.

The trick is to set the container's flex-direction to column, which means that:

  1. The flex-basis calculations will happen against the container's height, which we'll use to position the 1st and the 2nd children
  2. The flex-wrap will wrap the content to the right, which we'll use to position the 3rd and the 4th children

Example:

.container {
  height: 10rem;
  width: 30rem;
  background: lightgray;
  
  display: flex;
  /* by setting the flex-direction to "column" the 
  items that won't fit into the vertical space
  will be wrapped to the right */
  flex-direction: column;
  flex-wrap: wrap;
}

.child {
  box-sizing: border-box;
  border: 1px crimson solid;
  font-size: 3rem;
}

.child:nth-child(1),
.child:nth-child(2) {
  /* because we set the container's flex-direction
  to column, the flex-basis will make the children
  occupy the vertical space. In our case, because
  the 1st and the 2nd children are both 50%, they
  fill up the first column completely and push out
  the 3rd and the 4th children */
  flex: 0 1 50%;
}

.child:nth-child(3),
.child:nth-child(4) {
  flex: 0 1 100%;
}
<div class="container">
  <div class="child">1</div>
  <div class="child">2</div>
  <div class="child">3</div>
  <div class="child">4</div>
</div>
Alex Lomia
  • 6,705
  • 12
  • 53
  • 87