21

I have a page full of blocks which pile up with display: inline-block. I want to make some four or two times bigger, so I used float: left or right to put other blocks around.

My problem is if I have a five-element row, how could I put a bigger element in the middle of it? (as float put it naturally on the side).

Here's an example snippet:

#wrapper{
  width: 516px;
}
.block{
  display: inline-block;
  width: 90px;
  height: 50px;
  margin: 5px;
  background-color: red;
}
.bigger{
  height: 110px;
}
<div id="wrapper">
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block bigger"></div>
  <div class="block"></div>
  <div class="block"></div>
</div>

Here's what I would like to have from the snippet above Expected

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
PaulCo
  • 1,398
  • 4
  • 17
  • 31

2 Answers2

17

Flexbox Solution

You have fixed heights on your child elements (.block). Based on that information, we can extrapolate the height of the container (#wrapper).

By knowing the height of the container, your layout can be achieved using CSS Flexbox with flex-direction: column and flex-wrap: wrap.

A fixed height on the container serves as a breakpoint, telling flex items where to wrap.

#wrapper {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  height: 120px;
  width: 516px;
}
.block {
  width: 90px;
  flex: 0 0 50px;
  margin: 5px;
  background-color: red;
}
.bigger {
  flex-basis: 110px;
}
<div id="wrapper">
  <div class="block"></div>
  <div class="block"></div>
  <div class="block bigger"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
</div>

jsFiddle

Here's an explanation why flex items can't wrap unless there's a fixed height/width on the container: https://stackoverflow.com/a/43897663/3597276

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • 3
    I love flex layout so I really like this answer ! But what if you didn't knew the wrapper height ? – PaulCo Mar 30 '17 at 08:57
16

Grid Solution

For your layout to work with flexbox, you need to use nested containers or know the height of the container (see my other answer on this page). Not so with Grid. The code structure is very simple.

#wrapper {
  display: grid;                                     /* 1 */
  grid-template-columns: repeat(5, 90px);            /* 2 */
  grid-auto-rows: 50px;                              /* 3 */
  grid-gap: 10px;                                    /* 4 */
  width: 516px;
}
.bigger {
  grid-row: 1 / 3;                                   /* 5 */
  grid-column: 2 / 3;                                /* 6 */
}
.block {
  background-color: red;
}
<div id="wrapper">
  <div class="block"></div>
  <div class="block bigger"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
</div>

jsFiddle

Notes:

  1. Establish a block-level grid container. (spec reference)
  2. Instruct the grid to create a 90px width column, and repeat the process 5 times. (spec reference)
  3. Grid rows will be created implicitly (i.e., automatically, as necessary). Each implicit row should have a 50px height. (spec reference)
  4. The gutters around grid items. grip-gap is shorthand for grid-row-gap and grid-column-gap.(spec reference)
  5. Instruct the large item to span from row lines 1 to 3. (There are three row lines in a two-row grid.) (spec reference).
  6. Instruct the large item to span from grid column lines 2 to 3. (There are six column lines in a five-column grid.) (spec reference)
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701