The Cheeky Monkey Media Blog

A few words from the apes, monkeys, and various primates that make up the Cheeky Monkey Super Squad.

Drupal and Masonry banner

I recently had to create a new layout that mimicked the Pinterest layout. Masonry to the rescue! (sorta…) With Drupal already crapping out the content via views, we could just use the Masonry views plugin, right? Sorta. Well, it worked. … sorta. There were problems, and I don’t like problems, only solutions.

I like a very NON-hacky way of doing things. Masonry views worked for the desktop screen size but failed miserably for anything smaller. We were working with a responsive design, so it was unacceptable. There was simply just no amount of tweaking the options and CSS that it came with, that I was happy with. I’m also not a fan of CMS plugins controlling layout. There tend to be crappy implementations and far less control. I don’t speak for everything, of course, just my experience.

I wanted to control.. as much as I could. So I abandoned the views plugin, and just decided to use the raw jQuery plugin, and use my own CSS.

This assumes ya know how to use requireJS and jQuery plugins.

Step 1 – The view.

So, the view just had to output the HTML, nothing else. Set the output format for the view to ‘Unformatted list.’ Nice, just simple, clean Drupal output.

Step 2 – Including the jQuery plugin code.

I’m also not a fan of including boatloads of JS on every page so that you can use it “at some point” on some page on the site. Unnecessary load times, for all other pages.

RequireJS happiness ensued.

The main.js config file:

requirejs.config({
  paths: {
	// vendor
	'masonry': 'vendor/masonry.pkgd.min',

	// custom
'jquery': 'modules/jquery-global',
	'community': 'modules/community'
  }
});

require([
  'jquery',
  ], function ($) {
  'use strict';

   // DOM ready
  $(function() {

	// js loaded only on community page
	if ($('body').hasClass('page-community')) {
  	require(['community']);
	}

  }); // DOM ready
});

We’re telling require where to find the libraries and specific module files, that have the code we need. Then when DOM has loaded, we check to see if we’re on a specific page, if so, load up the required JS. The ‘community’ page is where the masonry plugin is required. So, let’s look at that file (community.js).

/**
 * Community
 * @requires jquery, masonry
 */
define([
  'jquery',
  'masonry'
], function ($, masonry) {
  'use strict';

  /**
   * object constructor
   */
  var Community = function() {
	this.init();
  };

  /**
   * init community module
   */
  Community.prototype.init = function() {
	var self = this;

	// init masonry
	$( '.view-community .view-content' ).masonry( { itemSelector: '.views-row' } );

  /**
   * DOM ready
   */
  $(function () {
	var community = new Community();
  });
});

So now we have the masonry jQuery plugin only loading up on the community page. By inspecting the output of that view on the page, I was able to figure out which elements to target for masonry to know which is which regarding content. The ‘.view-row’ elements were each ‘element’ of content, while the “.view-community .view-content” was the parent.

That just gets all the JS working, but will most likely still look like poo (technical monkey term). — Time to start slinging that poo around until we have something nice to look at. Yes, we can actually polish a turd.

Step 3 – CSS(SCSS) Kung-Poo

.view-community {
  max-width: 100%;
  margin: 0 auto;
  .view-content {
	width: 100%;
	overflow: hidden;
	.views-row {
  	width: 48%;
  	margin: 0 1%;
  	margin-bottom: rem-calc(20);
   	overflow: hidden;
  	border-radius: 15px;
  	background: $white;
  	font-size: rem-calc(12);
  	line-height: rem-calc(18);
  	@media #{$medium-up} {
    	font-size: rem-calc(16);
    	line-height: rem-calc(26);
  	}
  	@media #{$small-portrait-up} {
    	margin: 0 1%;
    	margin-bottom: rem-calc(20);
    	width: 48%;
  	}
  	@media #{$medium-up} {
    	margin: 0 1%;
    	margin-bottom: rem-calc(20);
    	width: 31%;
  	}
  	@media #{$large-up} {
    	margin: 0 1%;
    	margin-bottom: rem-calc(20);
    	width: 23%;
  	}

Okay, now we have something decent to look at.

  • So for mobile views, the elements take up 48% of the horizontal screen space, effectively having two elements per ‘row’.
  • Moving up from that, we just increase the font size.
  • Then up from that, (a tablet layout), we have effectively 3 per row, and for desktop, we have 4 per row.
  • So this is much cleaner, and leaner than having to fiddle with the views masonry plugin. It allows us to have much more control over the plugin itself and the CSS.

Sometimes, it pays to just go back to doing things manually, especially if you want more control.