Simple jQuery Plugin To Create Pinterest Style Grid Layout

John Avis by | March 9, 2016 | Jquery/Javascript Responsive Web Design

When I was looking for an alternative to Masonry to produce a responsive Pinterest style grid that was a lot simpler and lighter weight I came across this jQuery plugin on www.jqueryscript.net that is very simple and works well. However, It has a few issues which I needed to fix before I could use it.
When I was looking for an alternative to Masonry to produce a responsive Pinterest style grid that was a lot simpler and lighter weight I came across this jQuery plugin on www.jqueryscript.net that is very simple and works well.

However, It has a few issues which I needed to fix before I could use it.

1. The columns do not take up the full width of the container because the width calculation includes horizontal margin on all columns. It should exclude the margin on the final column.

2. The height calculation is inaccurate as it does not include vertical padding on every element. I needs to include padding for each element except the last one.

3. The function that runs to calculate and adjust sizes calls the window resize event handler every time it runs, which is not necessary, and results in the resize event running constantly. It is possible this was intended to handle loading of images, which effects the size calculation, which I deal with in issue 4.

4. If images are not loaded when the script runs then it can't calculate the height required correctly. To accommodate this, I run the resize event each time an image is loaded within the container.

Here's the final code. See the page on www.jqueryscript.net for instructions on how to use it.

UPDATE 13 April 2017: I've made some further improvements and fixes to this script. The new script allows you to create multiple breakpoints each with a specific number of columns. See my new post, Enhanced simple Pinterest Style Grid Layout jQuery Plugin.

UPDATE 16 Nov 2017: There's a new version available of this script available now that puts content in the shortest column rather than just in the next row/column position.

Note that the comments in the code show changes I made.

 /*
Pinterest Grid Plugin
Copyright 2014 Mediademons
@author smm 16/04/2014

usage:

$(document).ready(function() {
$('#blog-landing').pinterest_grid({
no_columns: 4
});
});
*/
; (function ($, window, document, undefined) {
var pluginName = 'pinterest_grid',
defaults = {
padding_x: 10,
padding_y: 10,
no_columns: 3,
margin_bottom: 50,
single_column_breakpoint: 700
},
columns,
$article,
article_width;

function Plugin(element, options) {
this.element = element;
this.options = $.extend({}, defaults, options);
this._defaults = defaults;
this._name = pluginName;
this.init();
}

Plugin.prototype.init = function () {
var self = this,
resize_finish;

$(".blog-landing img").load(function () {
$(window).resize();
});

$(window).resize(function () {
clearTimeout(resize_finish);
resize_finish = setTimeout(function () {
self.make_layout_change(self);
}, 11);
});

self.make_layout_change(self);

setTimeout(function () {
$(window).resize();
}, 500);
};

Plugin.prototype.calculate = function (single_column_mode) {
var self = this,
tallest = 0,
row = 0,
$container = $(this.element),
container_width = $container.width();
$article = $(this.element).children();

if (single_column_mode === true) {
article_width = $container.width() - self.options.padding_x;
} else {
//article_width = ($container.width() - self.options.padding_x * self.options.no_columns) / self.options.no_columns;
article_width = ($container.width() - self.options.padding_x * (self.options.no_columns - 1)) / self.options.no_columns;
}

$article.each(function () {
$(this).css('width', article_width);
});

columns = self.options.no_columns;

$article.each(function (index) {
var current_column,
left_out = 0,
top = 0,
$this = $(this),
prevAll = $this.prevAll(),
tallest = 0;

if (single_column_mode === false) {
current_column = (index % columns);
} else {
current_column = 0;
}

for (var t = 0; t < columns; t++) {
$this.removeClass('c' + t);
}

if (index % columns === 0) {
row++;
}

$this.addClass('c' + current_column);
$this.addClass('r' + row);

prevAll.each(function (index) {
if ($(this).hasClass('c' + current_column)) {
top += $(this).outerHeight() + self.options.padding_y;
}
});

if (single_column_mode === true) {
left_out = 0;
} else {
left_out = (index % columns) * (article_width + self.options.padding_x);
}

$this.css({
'left': left_out,
'top': top
});
});

this.tallest($container);
//$(window).resize();
};

Plugin.prototype.tallest = function (_container) {
var column_heights = [],
largest = 0;

var paddingy = this.options.padding_y;

for (var z = 0; z < columns; z++) {
var temp_height = 0;
_container.find('.c' + z).each(function () {
//temp_height += $(this).outerHeight();
temp_height += $(this).outerHeight() + paddingy;
});
column_heights[z] = temp_height;
}

//largest = Math.max.apply(Math, column_heights);
largest = Math.max.apply(Math, column_heights) - paddingy;
//_container.css('height', largest + (this.options.padding_y + this.options.margin_bottom));
_container.css('height', largest + this.options.margin_bottom);
};

Plugin.prototype.make_layout_change = function (_self) {
if ($(window).width() < _self.options.single_column_breakpoint) {
_self.calculate(true);
} else {
_self.calculate(false);
}
};

$.fn[pluginName] = function (options) {
return this.each(function () {
if (!$.data(this, 'plugin_' + pluginName)) {
$.data(this, 'plugin_' + pluginName,
new Plugin(this, options));
}
});
}

})(jQuery, window, document);


It's also easy to change the number of columns when it changes to "single column" mode by changing the Plugin.prototype.calculate method. Here's what the first part of this method should be changed to (comments show changes):

Plugin.prototype.calculate = function (single_column_mode) {
var self = this,
tallest = 0,
row = 0,
$container = $(this.element),
container_width = $container.width();
$article = $(this.element).children();

//these next lines are new
if (single_column_mode === true) {
columns = 2;
single_column_mode = false;
}
else {
columns = self.options.no_columns;
}

if(single_column_mode === true) {
article_width = $container.width() - self.options.padding_x;
} else {
//this next line has been changed
article_width = ($container.width() - self.options.padding_x * (columns - 1)) / columns;
}

$article.each(function() {
$(this).css('width', article_width);
});

//this next line should be removed
//columns = self.options.no_columns;

Related Posts

Jquery/Javascript Responsive Web Design

Yet another enhancement of the simple Pinterest Style Grid Layout jQuery Plugin

by John Avis | November 16, 2017

I have made another change to the modified version of Mediademons Simple jQuery Plugin To Create Pinterest Style Grid Layout - Pinterest Grid.


Jquery/Javascript

Back to top button like Facebook app

by John Avis | September 15, 2017

The Facebook app on Windows phone has a nice and unobtrusive back to top button that only appears once you scroll past a certain point, and only when you start scrolling up the page. This code offers similar functionality using jQuery.


Jquery/Javascript Responsive Web Design

Enhanced simple Pinterest Style Grid Layout jQuery Plugin

by John Avis | April 13, 2017

In response to a request, I have made some improvements to the modified version of Mediademon's Simple jQuery Plugin To Create Pinterest Style Grid Layout - Pinterest Grid.

Comments

Maxim Usik

by Maxim Usik | April 12, 2017

hi! thank you for your nice fixes! maybe you can help me with a little advice, please?

i would like to have a grid which changes from 3 columns at a desktop to 2 columns at ipad and 1 at iphone.
is it possible to do? and if yes how can i do it?

thank you very much!

Reply

John Avis

by John Avis | April 12, 2017

hi maxim. that's a great suggestion. i've made some changes to this script and it can now handle multiple breakpoints each with a specific number of columns. see my new post:
http://blog.johnavis.com/blog/828/enhanced-simple-pinterest-style-grid-layout-jquery-plugin/

Reply

Maxim Usik

by Maxim Usik | April 16, 2017

Wau! John, thank you very much for your quick answer! I will read it now! Thank you very much.

Reply

Kurt Hosna

by Kurt Hosna | May 17, 2017

This is great, thats for the post. I have a quick question, how can I control the width of the overall container. I know how to adjust the number of columns but I'd like the default width overall to be wider.

Reply

John Avis

by John Avis | May 17, 2017

Kurt, not sure I understand - the columns will be spaced evenly and will occupy the entire width of the element that you apply this to.You can put a fixed width on this element or it can be fluid. The plugin doesn't need to be "told" the width as it is responsive, and adapts to the available width on load and at resize.

Reply

John Avis

by John Avis | June 29, 2017

@kldamr, I'm not sure I understand. The plugin stacks the items from left to right, so the first one is top left, then each one is placed to the right and then down. Are you saying it is putting the first one not in the top left position? Do you have an example to look at?

You could modify the plugin fairly easy for RTL instead of LTR. If you need help with this I can have a look.

Reply

kldamr

by kldamr | June 30, 2017

thanks for you answer, In my case I use this pluc in with bootstrap-rtl, It's true that it stacks the items as you says (if I understand the logic of this plugin's code the order is assured by the two classes 'r' and 'c') i changer the order of the two classes but as I said before the first item still start in the middle. If you can help me to modify this plugin to use in RTL I will be highly grateful.

Reply

Leave a Comment
Tags
ASP.NET Html Forms ASP.NET MVC ASP.NET Web Forms ASP.NET Web Pages Bootstrap C# Classic ASP Cool Websites Databases eBay and PayPal Electrical Repairs General Hardware HTML/CSS Jquery/Javascript Media Center Mobile Phones Responsive Web Design SEO and Social Networking Web Design Web Development Web Security web+db Website Hosting Windows XP

About me

...mostly about web development and programming, with a little bit of anything else related to the Internet, computers and technology.

Subscribe

Get the latest posts delivered to your inbox.