Make a div span two rows in a grid

13,865

Solution 1

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

Solution 2

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)

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

Share:
13,865
PaulCo
Author by

PaulCo

Still a front-end lover ❤️, ReactJS liker ⚛️, fascinated by Python readability 🐍 and enjoying .NET Core sugar 🍯. Currently working as a consultant for enioka Haute Couture 👨🏼‍💻 Also doing some arty stuff on the side ✌🏻

Updated on July 18, 2022

Comments

  • PaulCo
    PaulCo almost 2 years

    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