17

Building off of a previous question, I'm trying to add bigger blocks to my grid layout. In the last question, I needed to have a div span multiple rows. The problem now is that I need a div to span multiple rows and columns.

If I have a five-element row, how could I put bigger elements in the middle of it? (as float puts 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;
}
.larger{
  height: 110px;
  width: 190px;
}
<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 larger"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
</div>

I don't want to use display: grid for the wrapper element, as Can I Use states this is a pretty on-the-edge technology right now. I was hoping for a non-grid, non-table solution.

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

3
  • 3
    Can the HTML be altered? Mar 30, 2017 at 17:15
  • If your HTML cannot be altered, I'd suggest using a library like Isotope - not sure there's a pure CSS solution that will really accomplish what you're going for.
    – maxinacube
    Mar 30, 2017 at 17:22
  • @Michael_B I am working on a '2 block wrapper' but would love another way to do it
    – PaulCo
    Mar 30, 2017 at 17:38

3 Answers 3

28

I understand that you are seeking an answer that doesn't involve HTML Tables or CSS Grid Layout. You mention that you don't want Grid because of weak browser support.

However, around the same time you posted your question, most major browsers released new versions which provide full support for Grid Layout (see details below).


CSS Grid makes your layout simple. There is no need to alter your HTML, add nested containers or set a fixed height on the container (see my flexbox answer on this page).

#wrapper {
  display: grid;                            /* 1 */
  grid-template-columns: repeat(5, 90px);   /* 2 */
  grid-auto-rows: 50px;                     /* 3 */
  grid-gap: 10px;                           /* 4 */
  width: 516px;
}

.tall {
  grid-row: 1 / 3;                          /* 5 */
  grid-column: 2 / 3;                       /* 5 */
}

.wide {
  grid-row: 2 / 4;                          /* 6 */
  grid-column: 3 / 5;                       /* 6 */
}

.block {
  background-color: red;
}
<div id="wrapper">
  <div class="block"></div>
  <div class="block tall"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block wide"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
</div>

jsFiddle

How it works:

  1. Establish a block-level grid container.
  2. The grid-template-columns property sets the width of explicitly defined columns. In this case, the grid is instructed to create a 90px width column, and repeat the process 5 times.
  3. The grid-auto-rows property sets the height of automatically generated (implicit) rows. Here each row is 50px tall.
  4. The grid-gap property is a shorthand for grid-column-gap and grid-row-gap. This rule sets a 10px gap between grid items. (It doesn't apply to the area between items and the container.)
  5. Instruct the .tall item to span from row lines 1 to 3 and column lines 2 to 3.*
  6. Instruct the .wide item to span from row lines 2 to 4 and column lines 3 to 5.*

* In a five-column grid there are six column lines. In a three-row grid there are four row lines.


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
  • This is great! Do you know how I can have an arbitrary box grow in size without any knowledge of its peers?
    – SB2055
    Jul 26, 2017 at 14:40
  • @SB2055, can you provide a bit more detail? Maybe a demo to work off of? Or consider posting a new question with full detail. Jul 28, 2017 at 11:17
5

Keeping your HTML as-is, the layout is not natively possible with flexbox. This is primarily because of the 2 x 2 box occupying the third and fourth columns. The closest you can get is this:

#wrapper{
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  align-content: flex-start;
  height: 180px;
  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"></div>
  <div class="block bigger"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block bigger"></div>
  <div class="block"></div>
  <div class="block bigger"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
</div>

As you can see, the big box is broken up between columns.

As mentioned in the other post you referenced, since you have fixed heights on your child elements (.block), we can determine the height of the container (.wrapper).

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

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

Alternatively, if you can add containers, then the layout is easy. Just create four nested flex containers to hold columns 1, 2, 3-4 and 5, and you're done.

#wrapper {
  display: flex;
  width: 516px;
}

section {
  display: flex;
  flex-direction: column;
}

.block {
  width: 90px;
  height: 50px;
  margin: 5px;
  background-color: red;
}

.bigger {
  flex-basis: 110px;
}

section:nth-child(3) {
  flex-direction: row;
  flex-wrap: wrap;
  flex: 0 0 200px;
}

section:nth-child(3)>.block:last-child {
  flex: 0 0 190px;
  height: 110px;
}
<div id="wrapper">
  <section>
    <div class="block"></div>
    <div class="block"></div>
    <div class="block"></div>
  </section>
  <section>
    <div class="block bigger"></div>
    <div class="block"></div>
  </section>
  <section>
    <div class="block"></div>
    <div class="block"></div>
    <div class="block"></div>
  </section>
  <section>
    <div class="block"></div>
    <div class="block"></div>
    <div class="block"></div>
  </section>
</div>

Otherwise, see this post for more details and other options:

1

To make it with flexbox and flex-direction: row.

#wrapper{
  width: 516px;
  display: flex;         /* added */
  flex-flow: row wrap;   /* added */
}
.block{
  display: inline-block;
  width: 90px;
  height: 50px;
  margin: 5px;
  background-color: red;
}
.block:last-child {
  margin-left: 205px;    /* added */
}
.bigger{
  height: 110px;
  margin-bottom: -55px;  /* added */
}
.larger{
  height: 110px;
  width: 190px;
  margin-left: 105px;    /* added */
  margin-bottom: -55px;  /* added */
}
<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 larger"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
</div>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.