Disclaimer
Many thanks to the people whose hard work as brought us WordPress, the Pinbin responsive theme and the Masonry javascript framework.
Symptoms
I have a WordPress 4.7.1 website. The website uses the Pinbin responsive theme. The responsive component is based on the Masonry javascript library. Masonry stacks individual articles in a grid style layout; the articles are automatically rearranged when the internet browser window is resized. The result is a pleasing layout where page content is arranged automatically to suit both large screen devices and small screen devices.
WordPress will normally display articles sorted by Publishing date. The most recent articles will be displayed first. Using the Pinbin responsive theme based on Masonry, the problem is that the articles appear ‘shuffled’. The order of the articles appears to be random at first (which is not the case).
Cause
Articles using the Masonry framework do not have a fixed height in pixels. Nor do they use the ‘Read more’ kind of intro text versus full article text. Some themes using the Masonry framework use an approach where each article is displayed capped at a fixed number of words. This determines the overal height of the article. By capping the length of an article by word count the height of each article is more or less consistent. Depending on the use of short or long words in an article the height of each article will vary slightly. Some articles may show an additional line of text for a sentence where others will not. The result is that not all articles are the exact same height, but it is a close match. This is a desirable feature as it is somewhat similar to how articles in a newspaper are laid out and is pleasing to the eye. Note that your eyes will still be able to recognize the colums -and in this case equally important- the rows of this particular grid layout.
The problem is that Masonry does not sort articles in a single row from left to right (for good reason). Masonry by default will stack the columns based on the height of previous articles; the shortest column will receive the first article on the next ‘row’. This is so that the vertical gap between articles is always filled first; it is the most efficient way to stack content. For content where the height of articles varies wildly, there are no recognizable rows and hence a left to right ‘ordering’ does not really apply. Left to right ordering only applies for content where articles are similar in height with only minimal variation.
The Masonry left-to-right sort order problem is described here:
https://github.com/desandro/masonry/issues/873
Unfortunately the thread is locked. Latest update Aug 22, 2016. Not sure if abandoned.
User ‘cavoirom’ suggests the following workaround:
Remove these lines of code:
var minimumY = Math.min.apply( Math, colGroup );
var shortColIndex = colGroup.indexOf( minimumY );
Add these line of code at the same position:
var shortColIndex = this.items.indexOf(item) % this.cols;
var minimumY = colGroup[shortColIndex];
This workaround is a great fix to resolve the left to right sort order feature request.
Implementation
cd .../wp-includes/js/ ls *masonry* masonry.min.js
/*!
* Masonry PACKAGED v3.3.2
* Cascading grid layout library
* http://masonry.desandro.com
* MIT License
* by David DeSandro
*/
GIT clone or download Desandro Masonry from here:
https://github.com/desandro/masonry
Unzip the downloaded file and place the following files in the WordPress folder where ‘masonry.min.js’ resides:
mv .../masonry-master/dist/*.js .../wp-includes/js/ ls *masonry* masonry.min.js masonry.pkgd.js masonry.pkgd.min.js mv masonry.min.js masonry.min.js.org cp masonry.pkgd.js masonry.min.js
Check to make sure your WordPress theme masonry effect still works.
Now we can edit the “masonry.min.js” file as follows:
// how many columns does this brick span var remainder = item.size.outerWidth % this.columnWidth; var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil'; // round if off by 1 pixel, otherwise use ceil var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth ); colSpan = Math.min( colSpan, this.cols ); var colGroup = this._getColGroup( colSpan ); // get the minimum Y value from the columns var minimumY = Math.min.apply( Math, colGroup ); var shortColIndex = colGroup.indexOf( minimumY ); var shortColIndex = this.items.indexOf(item) % this.cols; var minimumY = colGroup[shortColIndex]; // position the brick var position = { x: this.columnWidth * shortColIndex, y: minimumY };
By inserting the text in green the sort order will be left-to-right at all times. As this only suits Masonry websites where the height of articles varies only slightly (i.e. where your eye can detect individual ‘rows’ still), this code fix should be considered a workaround and not a solution. Most likely some additional logic or manual toggle may be required to enable this behaviour only when required.
You can see the sort order being preserved when you resize your internet browser window on the following web site, for example: