The Startup
Published in

The Startup

How to Add a Masonry Gallery With CSS (and Ruby on Rails) the Basic Way

Storyboard scene of Prin from Paper Space® (catching the meteoroid by the grains)

Backstory

Our startup has been undergoing a lot of change over the past few months (as I mention briefly in my Everything I wish I Knew post). Part of that change has been switching from Python + Django to Ruby + Ruby on Rails to build out our vision for a re-imagined social media experience, as well as a new version of Sara’s website to support her design + architecture work.

It’s felt a bit like Prin up there catching hold of a meteoroid and trying to hang on for dear life.

Like a ride through the galaxy, our pivots have been full of discovery, inspiration, and learning.

For Sara’s new website, featuring a shuffling masonry grid visual layout for some of her work, we wanted to find a simple and robust solution — here it is.

Prerequisites

To shorten this read and get right to the “good stuff”, I’m going to assume that you have a working Ruby on Rails application (Rails app), are familiar with your CSS framework of choice (e.g. Bootstrap or Tailwind CSS), and have a working Model-View-Controller (MVC) setup to power your imagery.

In short, you’re here because either (a) you just want to figure out the CSS bits and/or (b) you enjoy reading what I’ve got to say (you sweetheart you).

Preface

When I was trying to figure this out, I found a lot of complicated solutions with JavaScript and lots of different CSS “hacks” that never held up if you were displaying images dynamically (“don’t set your container height less than your tallest column or you’ll be sorry”).

To be clear, I’m sure the JavaScript solutions hold up, and are probably the most super-dope-super-fast options out there, but I didn’t try them because I’m not that fluent in JavaScript at the moment (I stick to a little Stimulus right now).

I needed a CSS solution, one that was fairly robust, and one that wasn’t a nightmare to implement.

Thankfully, I discovered this post which noted that the CSS Working Group published a W3C draft (World Wide Web Consortium), back in October of 2019, that enables exactly the kind of functionality I was looking for.

Let’s get to it

Below is a bit of our setup for Sara’s new site (assuming you have something similar working):

  1. Ruby on Rails app
  2. Tailwind CSS
  3. Gallery MVC setup
  4. JavaScript pack tag setup

If you’ve successfully setup a similar system (using Sassy CSS too), then you should have something like this in your application.html.erb file (it could also be rendered from a partial):

<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>

With this setup in hand, we’ve got a components directory inside of a stylesheets directory inside of our javascript directory inside of our app directory, or rather:

app/javascript/stylesheets/components

Inside of the components directory we will create a new Sassy CSS (SCSS) file:

# Title this file per your use caseapp/javascript/stylesheets/components/gallery.scss

Inside our new gallery.scss file we will write the CSS code for our masonry grid layout:

# Again, use titles appropriate to your use case.gallery-container {
column-count: #insert column number here;
column-gap: #insert the space between columns here (i.e. 1em);
}
.gallery-item {
display: inline-block;
margin: # margin spacing for each item (i.e. 0 0 1em);
width: 100%;
}

A couple things to note about the gallery.scss code:

  • It is written to allow for our dynamic gallery, accounting for unknown numbers of images
  • It is intentionally not responsive in the sense that we wanted that gallery feel across all screen sizes.

We will now need to make sure that we import that new gallery.scss file into our application.scss file (which is inside of our stylesheets directory but outside of our components):

# app/javascript/stylesheets/application.scss
# This is assuming you've setup your application similarly
@import "components/gallery"; # add this line with your file name

If you haven’t setup your application in this way, and you would like to, then you should do this as well (skip this step if you’ve done this or similar already):

# app/javascript/packs/application.jsimport "stylesheets/application" # add this line# Change the app/assets/stylesheets/application.css file to .scssapp/assets/stylesheets/application.css => application.scss

With that said, let’s see now how that fits into our view:

# This would be your appropriate filename.html.erb
# This code is the "bare bones" as the look will depend on your app's styling
<% if @models.exists? %>
<div class="gallery-container"> # The masonry grid container
<% @models.shuffle.each do |model| %>
<div class="gallery-item shadow-lg rounded"> # Masonry item
<%= link_to image_tag(model.model_image), model %>
</div>
<% end %>
</div>
<% end %>

Note: You could always put the masonry CSS (that we put in gallery.scss) in other folders, or directly in your HTML file, or wherever your CSS setup requires.

That’s it!

Now, in our example there’s a bit of logic to account for the fact that we wanted Sara’s gallery to shuffle each time you look at it and to account for its’ dynamic nature (e.g. adding or removing images at will).

The actual CSS required to achieve the masonry grid layout is incredibly succinct and easy to understand — just like the “Rails way”.

Addendum

If you would like your masonry to be responsive in the sense that it switches the number of columns per screen size (media query), then definitely check out the post I mentioned near the start of this article.

Also, you can do far more things stylistically, but I left a lot of that stuff out because that’s where you get to put the you magic into it (or your client or boss or whoever).

Now you know a very clean and simple way to quickly put together a fairly robust masonry grid layout using nothing but a few simple CSS lines of code.

Hope it helps!

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store