sam
sam

Reputation: 253

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

Upvotes: 2

Views: 3278

Answers (3)

Hossein Azizdokht
Hossein Azizdokht

Reputation: 1005

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>

Upvotes: 5

Fred
Fred

Reputation: 1789

There is an upcoming specification that adds masonry layout to the grid module of CSS. Unfortunately it is not supported by any browser yet: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout/Masonry_layout

In my VueJS apps I'm using the following plugin for masonry layout: https://vue-masonry-wall.yeger.eu/ It works well enough.

Maybe you can dig into the code and figure out how they have implemented it.

Upvotes: -1

Armaniimus
Armaniimus

Reputation: 67

I was able to create your image with the grid system with the code below using the grid system as was hinted by you with a grid 3fr wide and 8fr long.

widths

To create the width items with class grid-33 have span 1 fraction and items with class grid-66 span 2 fractions in width

heights

in your picture item 1, 4 and 7 are around 2 / 3ths of the the other items. Because of this there height is set to 2 fractions and the remaining are set to 3 fractions.

gaps

To keep the correct gaps I kept your margins as grid-gap didnt seem to work. and to give the items the correct height I changed heigth to auto, so there are no empty spaces.

/*CSS */
.container {
  display: grid; /* changed */
  padding: 15px 15px 0 0;
  background: #CDD6D0;
  
  grid-template: repeat(8, 1fr) / repeat(3, 1fr); /* added */
}

.g {
    background: #E16036;
    border: 4px solid #E3170A;
    border-radius: 8px;
    padding: 15px;
    color: white;
    font: 18px Arial;

    grid-row-end: span 2; /* added */
    grid-column-end: span 1; /* added */
    
    margin: 7.5px; /* changed */
    height: auto; /* changed */
}

.g-h-3 {
  grid-row-end: span 3; /* added */
}

.grid-33 {
  grid-column-end: span 1; /* added */
}

.grid-66 {
  grid-column-end: span 2; /* added */
}
<!-- HTML Markup: -->
<div class="container">
  <div class="g grid-33">Item 1</div>
  <div class="g grid-66 g-h-3">Item 2</div>
  <div class="g grid-33 g-h-3">Item 3</div>
  <div class="g grid-33">Item 4</div>
  <div class="g grid-33 g-h-3">Item 5</div>
  <div class="g grid-66 g-h-3">Item 6</div>
  <div class="g grid-33">Item 7</div>
</div>

Upvotes: 0

Related Questions