7

I have a masonry grid using masonry/packery js plugin in a CMS and it is very cumbersome for the users to manage the images because they need to be exact ratios to get the proper brick effect and fill all the gaps which is a big pain for the non technical users of the cms to update or change images. Also the plugin is slow to initialize.

Are there any modern html solutions or newer js plugins out there nowadays with newer tech like possibly flexbox or css grid that would give me the same masonry effect without having to predefine the ratios of every image and make it so the users of the cms can just upload any size image and it will fit in a packery layout without having to define where it should be in the layout or resize the image on upload?

Note this is in custom cms so I am looking for answers that are not specific to the cms platform like WordPress.

Jithin Raj P R
  • 5,957
  • 6
  • 30
  • 64
zanedev
  • 558
  • 5
  • 16

4 Answers4

7

Rafaela Ferro wrote an article on medium that goes into amazing detail on creating masonry style image layouts using CSS grid that allow for great flexibility. Its less than 30 lines of CSS and is responsive as well.

By taking advantage of image object-fit: cover, the images can be any size and the grid will take care of the rest. The only thing the user would probably want to do is make sure the image looks good when zoomed into the center (due to object-fit).

Code taken directly from her article:

.gallery { 
  display: grid;
  grid-gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  grid-auto-rows: 250px 150px;
  grid-auto-flow: dense;
}

.gallery .item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (min-width: 480px) {
  .gallery .item:first-child {
    grid-area: 1 / 1 / span 2 / span 2;
  } 
  
  .gallery .item:nth-child(3n) {
    grid-column: span 2;
  }
}
<div class="gallery">
  <div class="item">
    <img src="https://images.dog.ceo/breeds/weimaraner/n02092339_431.jpg">
  </div>
  
  <div class="item">
    <img src="https://images.dog.ceo/breeds/leonberg/n02111129_17.jpg">
  </div>
  
  <div class="item">
    <img src="https://images.dog.ceo/breeds/borzoi/n02090622_5890.jpg">
  </div>
  
  <div class="item">
    <img src="https://images.dog.ceo/breeds/elkhound-norwegian/n02091467_3090.jpg">
  </div>
  
  <div class="item">
    <img src="https://images.dog.ceo/breeds/dingo/n02115641_7158.jpg">
  </div>
  
  <div class="item">
    <img src="https://images.dog.ceo/breeds/bluetick/n02088632_2149.jpg">
  </div>
  
  <div class="item">
    <img src="https://images.dog.ceo/breeds/bluetick/n02088632_1625.jpg">
  </div>
  
  <div class="item">
    <img src="https://images.dog.ceo/breeds/ridgeback-rhodesian/n02087394_9369.jpg">
  </div>
  
  <div class="item">
    <img src="https://images.dog.ceo/breeds/dachshund/dog-495133_640.jpg">
  </div>
  
  <div class="item">
    <img src="https://images.dog.ceo/breeds/chow/n02112137_8212.jpg">
  </div>
</div>
Steven Lambert
  • 4,942
  • 1
  • 24
  • 43
  • Exactly what I was looking for! I knew I read some articles but couldn't find them in my sea of saved links. I modified it a bit by adding some javascript for a filter and it works beautifully! – zanedev Jul 22 '18 at 19:18
0

I think this will work for you fine.

It's a CSS solution in which you can use any size images and it will be in 3 column layout.

body{
  height:500px;
}

ul {
    list-style: none;
    -moz-column-count: 3; /*change this to change the grid column count*/
    -webkit-column-count: 3; /*change this to change the grid column count*/
    column-count: 3; /*change this to change the grid column count*/
    -moz-column-gap: 1em;
    -webkit-column-gap: 1em;
    column-gap: 1em;
    padding: 0px 4px 4px 4px;
    margin-top: -10px;
    display: inline-block;
    width: 100%;
    overflow:visible;
    
}

li {
    width: 100%;
    display: inline-block;
    float:left;
    background: transparent;
    box-sizing: border-box;
    -moz-box-sizing: border-box;
    -webkit-box-sizing: border-box;
    margin: 1%;
}

li div {
    border-radius: 3px;
    background-color: #f4faff;
    margin-top: 1em;
    cursor: pointer;
}

li div img{
    height: auto;
    width: 100%;
    vertical-align: middle;
    border: 1px solid #ddd;
}
<ul>
    <li><div><img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQs7OT7p9xBXn090AjKYgX4eV6vr-kHsmbIfcSFh__PoXgdNtb5gg" alt=""></div></li>
    <li><div><img src="https://cdn.pixabay.com/photo/2016/10/27/22/53/heart-1776746_960_720.jpg" alt=""></div></li>
    <li><div><img src="https://images7.alphacoders.com/346/346251.jpg" alt=""></div></li>
    <li><div><img src="https://wallpaperbrowse.com/media/images/img_fjords.jpg" alt=""></div></li>
    <li><div><img src="https://www.iloveshayari.in/wp-content/uploads/2018/01/good-morning-lovely-images-1024x932.jpg" alt=""></div></li>
    <li><div><img src="http://www.whoa.in/20130627-Whoa/pink-natural-wallpaper.jpg" alt=""></div></li>
    <li><div><img src="https://www.usnews.com/dims4/USNEWS/ff9c2b0/2147483647/thumbnail/1280x480%5E/quality/85/?url=http%3A%2F%2Fmedia.beam.usnews.com%2Fdf%2F15%2F24d3553c442296f8206e9698bf6c%2Fresizes%2F1500%2Fbs18.sub.nat.environment.jpg" alt=""></div></li>
</ul>

But there is a bug in this solution - which I have reported recently. But you will not face this bug if don't use box-shadow with it.

I hope this helps you.

Jithin Raj P R
  • 5,957
  • 6
  • 30
  • 64
0

What you are looking for must be object-fit. Just set the height and width you want with css and then, apply object-fit: cover to the img tag. Your image will act as background-size: cover.

Mahesh Samudra
  • 314
  • 1
  • 5
  • 12
0

Have you considered using CSS Columns instead? I've used something similar to below with no issues. It also allows for great flexibility between @media breakpoints.

EDIT: It also currently has better support than CSS Grid (as of June 2018).

.columns__container {
  column-count: 3;
  column-gap: 15px;
  counter-reset: item-counter;
}

/* OR, with arbitrary media queries */

.columns__container {
  column-count: 2;
  column-gap: 15px;
  counter-reset: item-counter;
}
@media screen and (min-width: 576px) {
  .columns__container {
    column-count: 3;
  }
}
@media screen and (min-width: 768px) {
  .columns__container {
    column-count: 4;
  }
}
@media screen and (min-width: 992px) {
  .columns__container {
    column-count: 5;
  }
}
@media screen and (min-width: 1200px) {
  .columns__container {
    column-count: 6;
  }
}
<div class="columns__container">
  <figure>
    <img src="..." alt="..." />
    <figcaption>...</figcaption>
  </figure>
  <figure>
    <img src="..." alt="..." />
    <figcaption>...</figcaption>
  </figure>
  <figure>
    <img src="..." alt="..." />
    <figcaption>...</figcaption>
  </figure>
</div>