skip to Main Content

Can anyone please guide me how to created this type of masonry layout? Is it possible to create this type masonry gallery using display: grid and how to overlap the layers? Is there any other way to create this?

I’ve tried using the below code but that does not seem good. I also want to make it responsive.

masonry gallery image

.masonry-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-column-gap: 0px;
  grid-row-gap: 0px;
}

.masonry-grid .grid-item {
  position: relative;
}

.masonry-grid .grid-item img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.item-1 {
  grid-area: 1 / 1 / 2 / 2;
  height: 230px;
  margin: 20px -140px 0 0;
  z-index: 2;
}

.item-2 {
  grid-area: 1 / 2 / 3 / 3;
  height: 465px;
  z-index: 1;
}

.item-3 {
  grid-area: 1 / 3 / 4 / 4;
  max-height: 765px;
  margin-top: 20px;
  margin-right: -40px;
  z-index: 1;
}

.item-4 {
  grid-area: 1 / 4 / 2 / 5;
  /*margin-left: -40px;*/
  margin-right: 20px;
}

.item-5 {
  grid-area: 2 / 1 / 4 / 2;
  max-height: 585px;
  margin: -40px -10px 0 0;
}

.item-6 {
  grid-area: 3 / 2 / 4 / 3;
  max-height: 350px;
  margin: -160px -90px 0 0;
}

.item-7 {
  grid-area: 2 / 4 / 3 / 5;
  margin: 20px 0 0 -40px;
  z-index: 1;
}

.item-8 {
  grid-area: 4 / 1 / 5 / 2;
  max-height: 540px;
  margin: -300px 0 0;
}

.item-9 {
  grid-area: 4 / 2 / 6 / 3;
  max-height: 650px;
  width: 650px;
  margin: -310px 0 0 -50px;
}

.item-10 {
  grid-area: 4 / 3 / 5 / 4;
  margin: -491px 0 0;
}

.item-11 {
  grid-area: 3 / 4 / 4 / 5;
  margin: -50px 0 0 40px;
}

.item-12 {
  grid-area: 5 / 3 / 6 / 4;
  margin: -186px 0 0 -40px;
  z-index: 1;
}

.item-13 {
  grid-area: 4 / 4 / 5 / 5;
  margin: 50px 0 0 -50px;
  max-width: 480px;
}
<div class="masonry-grid">
  <div class="grid-item item-1">
    <img src="1.png" alt="">
  </div>
  <div class="grid-item item-2">
    <img src="2.png" alt="">
  </div>
  <div class="grid-item item-3">
    <img src="3.png" alt="">
  </div>
  <div class="grid-item item-4">
    <img src="4.png" alt="">
  </div>
  <div class="grid-item item-5">
    <img src="5.png" alt="">
  </div>
  <div class="grid-item item-6">
    <img src="6.png" alt="">
  </div>
  <div class="grid-item item-7">
    <img src="7.png" alt="">
  </div>
  <div class="grid-item item-8">
    <img src="8.png" alt="">
  </div>
  <div class="grid-item item-9">
    <img src="9.png" alt="">
  </div>
  <div class="grid-item item-10">
    <img src="10.png" alt="">
  </div>
  <div class="grid-item item-11">
    <img src="11.png" alt="">
  </div>
  <div class="grid-item item-12">
    <img src="12.png" alt="">
  </div>
  <div class="grid-item item-13">
    <img src="13.png" alt="">
  </div>
</div>

2

Answers


  1. What you are doing looks okay, given the design.

    However, I think this is the kind of design you want to push back against since it has several flaws:

    • arbitrary gaps
    • arbitrary overlaps
    • you need 4 different z-indexes and it’s hard to see "a rule"
    • hard to scale (what if there twice as much images, I don’t really see the logic of the design)

    So, I would start with making an interpretation of the design that is more clear/logical.

    EG:

    • I would start with an unsplash kindof layout, but 4 instead of 3 columns. (its also grid-based)
    • you probably need to alter the html a bit: lets wrap your grid-items in col-wrappers: .masonry-grid > .col-wrapper
    • I would not explicitly set the height or the width of any grid item, but keep the same width everywhere, and let the image decide the height to keep the original dimensions.
    • I would try to alternate the z-index & overlap behavior with a smart css rule based on the nth-child(odd) and nth-child(even) pseudo-selectors. (The negative margin might seem like a crazy hack, but if it works, why not. You can also try to get there using translate: scale(1.05) and transform: scale(0.95) or using the translate property.

    eg:

    .masonry-grid .col-wrapper:nth-child(odd) .grid-item:nth-child(odd) {
      [...]
    }
    .masonry-grid .col-wrapper:nth-child(even) .grid-item:nth-child(odd) {
      [...]
    }

    Responsiveness:

    you can use the media query, eg: @media only screen and (max-width: 600px) and (min-width: 400px) {...} to have different rules on different breakpoints.

    The above mentioned, would only work on big sizes.
    If you go a bit smaller, 3 columns would be enough.
    If you go to smartphone size, you should just display the images above and below each other.

    Note: your HTML would look different depending on the amount of columns (or the breakpoints). This adds a difficulty level, but I don’t think you can have it without the using .col-wrapper.

    Hope that helps

    Login or Signup to reply.
  2. To get some order out of the seeming chaos, as you have spotted, the layout looks roughly like a grid with 4 columns.

    If we also have four rows, the whole based on a square, we could start with a 4×4 grid with images (in this case a background color as in your picture just for demo) each roughly in the grid item space they seem associated with.

    This gives you:

    enter image description here

    The point of this being that we can then size and position each image relative to its grid square. This can be done easily, if tediously, by measuring the width/height/left/top of each item in the original design picture and using them as
    percentages of the grid item each is in.

    That way we get responsiveness.

    I do not claim to have done any accurate measuring, and I got a bit bored part way through, so here is a snippet with the first half of the imgs sort of positioned and sized as a demo. You will of course want to get out the ruler and be more accurate.

    Note the z-indexes. Just for simplicity, 0 is given to an img which doesn’t overlap any other item and 3 is given to an img which isn’t overlapped by any other item. Then 1 and 2 are allocated to those in between that do some overlapping and are themselves partly overlapped.

    <div class="masonry-grid">
      <div class="grid-item item-1">
        <img src="1.png" alt="">
      </div>
      <div class="grid-item item-2">
        <img src="2.png" alt="">
      </div>
      <div class="grid-item item-3">
        <img src="3.png" alt="">
      </div>
      <div class="grid-item item-4">
        <img src="4.png" alt="">
      </div>
      <div class="grid-item item-5">
        <img src="5.png" alt="">
      </div>
      <div class="grid-item item-6">
        <img src="6.png" alt="">
      </div>
      <div class="grid-item item-7">
        <img src="7.png" alt="">
      </div>
      <div class="grid-item item-8">
        <img src="8.png" alt="">
      </div>
      <div class="grid-item item-9">
        <img src="9.png" alt="">
      </div>
      <div class="grid-item item-10">
        <img src="10.png" alt="">
      </div>
      <div class="grid-item item-11">
        <img src="11.png" alt="">
      </div>
      <div class="grid-item item-12">
        <img src="12.png" alt="">
      </div>
      <div class="grid-item item-13">
        <img src="13.png" alt="">
      </div>
      <div class="grid-item item-13">
        <img src="13.png" alt="">
      </div>
      <div class="grid-item item-13">
        <img src="13.png" alt="">
      </div>
      <div class="grid-item item-13">
        <img src="13.png" alt="">
      </div>
    </div>
    <style>
      .masonry-grid {
        margin-left: 200px;
        display: grid;
        width: 100vmin;
        aspect-ratio: 1;
        grid-template-columns: repeat(4, 1fr);
        grid-template-rows: repeat(4, 1fr);
        grid-column-gap: 0px;
        grid-row-gap: 0px;
        position: relative;
      }
      
      .masonry-grid .grid-item {
        position: relative;
        width: 100%;
        height: 100%;
      }
      
      .masonry-grid .grid-item img {
        --w: 100%;
        --h: 100%;
        --l: 0;
        --t: 0;
        width: var(--w);
        height: var(--h);
        object-fit: contain;
        left: var(--l);
        top: var(--t);
        z-index: var(--z);
        background-color: var(--b);
        box-sizing: border-box;
        position: absolute;
      }
      
      .masonry-grid .grid-item.item-1 img {
        --w: 100%;
        --h: 40%;
        --l: 10%;
        --t: 10%;
        --z: 2;
        --b: pink;
      }
      
      .masonry-grid .grid-item.item-2 img {
        --w: 100%;
        --h: 100%;
        --l: 0%;
        --t: 0%;
        --z: 1;
        --b: magenta;
      }
      
      .masonry-grid .grid-item.item-3 img {
        --w: 120%;
        --h: 200%;
        --l: -10%;
        --t: 5%;
        --z: 2;
        --b: darkSlateBlue;
      }
      
      .masonry-grid .grid-item.item-4 img {
        --w: 80%;
        --h: 50%;
        --l: -10%;
        --t: 0%;
        --z: 2;
        --b: teal;
      }
      
      .masonry-grid .grid-item.item-5 img {
        --w: 110%;
        --h: 150%;
        --l: 0%;
        --t: -20%;
        --z: 0;
        --b: brown;
      }
      
      .masonry-grid .grid-item.item-6 img {
        --w: 60%;
        --h: 60%;
        --l: 30%;
        --t: 5%;
        --z: 3;
        --b: cyan;
      }
      
      .masonry-grid .grid-item.item-7 {
        grid-column: 4;
      }
      
      .masonry-grid .grid-item.item-7 img {
        --w: 100%;
        --h: 75%;
        --l: 10%;
        --t: -30%;
        --z: 3;
        --b: lime;
      }
      
      .masonry-grid .grid-item.item-8 img {
        --w: 75%;
        --h: 100%;
        --l: 10%;
        --t: 30%;
        --z: 3;
        --b: orange;
      }
      
      .masonry-grid .grid-item.item-9 img {
        --b: red;
      }
      
      .masonry-grid .grid-item.item-10 img {
        --b: gray;
      }
      
      .masonry-grid .grid-item.item-11 img {
        --b: orange;
      }
      
      .masonry-grid .grid-item.item-12 {
        grid-column: 3;
      }
      
      .masonry-grid .grid-item.item-12 img {
        --b: magenta;
      }
      
      .masonry-grid .grid-item.item-13 img {
        --b: orange;
      }
    </style>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search