htmlflexboxcss-gridgrid-layoutmasonry

CSS Grid with variable height to make it work like masonry layout


I'm trying to create masonry layout using css grid layout. All items in grid have variable heights. The items in the next row should stack to available space of the items in the previous row. i tried using flex-flow: row wrap but it doesn't work. Below is what i'm trying to achive.

enter image description here

Html Markup:

<div class="container">
  <div class="g grid-33">Item 1</div>
  <div class="g grid-66">Item 2</div>
  <div class="g grid-33">Item 3</div>
  <div class="g grid-33">Item 4</div>
  <div class="g grid-33">Item 5</div>
  <div class="g grid-66">Item 6</div>
  <div class="g grid-33">Item 7</div>
</div>

CSS

.container {
  display: flex;
  flex-wrap: wrap;
  padding: 15px 15px 0 0;
  background: #CDD6D0;
}

.g {
    background: #E16036;
    border: 4px solid #E3170A;
    border-radius: 8px;
    padding: 15px;
    color: white;
    font: 18px Arial;
    margin: 0 0 15px 15px;
    height: fit-content;
}

.grid-25 {
  width: calc(25% - 15px);
}

.grid-33 {
  width: calc(33.3333% - 15px);
}

.grid-50 {
  width: calc(50% - 15px);
}

.grid-66 {
  width: calc(66.6666% - 15px);
}

.grid-100 {
  width: calc(100% - 15px);
}

.g:nth-child(2) {
    height: 100px;
}

.g:nth-child(3) {
    height: 90px;
}

.g:nth-child(6) {
    height: 100px;
}

.g:nth-child(5) {
    height: 90px;
}

Codepen link


Solution

  • Your rows and columns should be compatible with grid-template. check out this solution

    .container {  display: grid;
      grid-template-columns: repeat(3, 1fr);
      grid-template-rows: repeat(5, 1fr);
      gap: 1em 1em;
      grid-auto-flow: row;
      padding: 1rem;
      grid-template-areas:
        "a b b"
        "c b b"
        "c d e"
        "f f e"
        "f f g";
    }
    
    .a { grid-area: a; }
    
    .b { grid-area: b; }
    
    .c { grid-area: c; }
    
    .d { grid-area: d; }
    
    .e { grid-area: e; }
    
    .f { grid-area: f; }
    
    .g { grid-area: g; }
    
    
    
    html, body , .container {
      min-height: 100%;
      margin: 0;
      background: #fff;
      font-family: "Helvetica Neue";
      color: #A770F1;
    }
    
    .container > div[class] {
      background: #ececec;
      position: relative;
      border-radius: 1rem;
      font-weight: bold;
      display: grid;
      align-items: center;
      justify-content: center;
      text-align: center;
      padding: 1rem;
    }
    
    .black {
      color: #000;
    }
    <div class="container">
      <div class="a black">a</div>
      <div class="b">b</div>
      <div class="c">c</div>
      <div class="d">
    d
      </div>
      <div class="e">
     e
      </div>
      <div class="f">
    f
      </div>
      <div class="g">g</div>
    
    </div>