This is a guest post by Josh Pollock
The Pinterest-like grid display of posts has been a popular design for WordPress blog index pages for a while. It is popular not only because it mimics the look of the popular social media site, but also because it makes the best use of space on the screen. On a WordPress blog index, it allows each post preview to be the size it naturally needs to be, without leaving extra space.
In this tutorial, I will show you how to use the popular Masonry JavaScript Library to create cascading grid layouts for your blog index, as well as archive pages for your theme. I will address a few issues that you need to consider for mobile-optimization and how to solve them.
Note: This is an advanced level tutorial for those who feel comfortable editing WordPress themes and have sufficient HTML/CSS knowledge.
Step 1: Add Necessary Libraries To Your Theme
Before we begin, you will need to get two files, both by David DeSandro and add them to your theme’s JS directory. The first is Masonry 3, and the second is ImaglesLoaded, which will allow us to have Masonry delay calculating the grid layout until it has all the image sizes it needs, which is important to avoid certain layout issues.
WordPress includes Masonry 2, but has not been updated to version 3 as of WordPress 3.7. As a result we will need to deregister the included Masonry, something that I would normally never do, but there is nothing I can do about it. As you will see in the function below we are only adding Masonry 3 to the front-end, not the admin, where the included Masonry is essential.
Here is the function and action for adding the two libraries, along with a style sheet for Masonry:
One thing to notice is that for Masonry, we are passing the ‘imagesLoaded’ handle in the third parameter for wp_enqueue_scripts(), which is the dependency argument, (see our guide on how to properly add JavaScripts and Styles in WordPress). This will ensure that Masonry is always loaded after imagesLoaded, and will only be loaded when Masonry is loaded. Also note that we are not adding jQuery as a dependency for either. One of the advantages of Masonry 3 over, Masonry 2 is that it does not require jQuery, but can be used with it. In my experience, initializing Masonry without jQuery is more reliable, and opens up the possibility of skipping loading jQuery, which can help with both page load times and compatibility issues.
Step 2: Initialize The Javascript
This next function sets up Masonry, defines the containers that will be used with it and also makes sure everything happens in the right order. Masonry needs to do calculate the size of each of the items on the page in order to layout its grid dynamically. A problem I’ve run into with Masonry in many browsers is that Masonry will miscalculate the height of items with slow loading images, leading to overlapping items. The solution is to use imagesLoaded to prevent Masonry from calculating the layout until all images are loaded. This ensures proper sizing.
This is the function and action that will output the initialization script in the page footer:
The function is explained step by step with inline comments. What the Javascript function does is tell Masonry to look inside a container with the id “masonry-loop” for items with the class “masonry-entry” and to calculate the grid only after images are loaded. We set the outer container with querySelector and the inner with itemSelector.
Step 2: Create Masonry Loop
Instead of adding the HTML markup for Masonry directly to a template we are going to create a separate template part for it. Create a new file called “content-masonry.php” and add it to your theme. This will allow you to add the Masonry loop to as many different templates as you want.
In your new file you will add the code shown below. The markup is similar to what you would normally see for any content preview. You can modify it anyway you need to, just be sure that the outermost element has the class of “masonry-entry” that we set as the itemSelector in the last step.
This markup has classes for each of its parts so you can add markup to match your theme. I like adding a nice, slightly rounded border to .masonry-entry. Another nice option is no border for .masonry-entry, but to give it a slight shadow. That looks particularly good when the post thumbnail extends the whole way to the border of the container, which can be accomplished by giving .masonry-thumbnail margins and paddings of 0 in all directions. You will want to add all of these styles in a file called masonry.css in your theme’s css directory.
Step 3: Add Masonry Loop To Templates
Now that we have our template part you can use it in any template in your theme you like. You might add it to index.php, but not category.php if you don’t want it used for category archives. If you only want it used on your theme’s home page, when its set to show blog posts, you would use it in home.php. Wherever you choose all you need to do is wrap your loop in a container with the id “masonry-loop” and add the template part into the loop using get_template_part(). Be sure to start the masonry loop container before while (have_posts() ).
For example, here is the main loop from twentythirteen’s index.php:
And here it is modified to get use our Masonry loop:
Step 4: Set Responsive Widths of Masonry Items
There are several ways that you can set the width of each Masonry item. You can set the width using a number of pixels when you initialize Masonry. I’m not a fan of doing that since I use responsive themes and it requires some complex media queries to get things right on small screens. For responsive designs, I’ve found the best thing to do is set a width value for .masonry-entry with a percentage, based on how many items you want in a row and let Masonry do the rest of the math for you.
All this requires is dividing the 100 by the number of items you want to set the percentage in a simple entry in your theme’s style.css. For example, if you want four items in each row you could do this in your masonry.css file:
.masonry-entry{width:25%}
Step 5: Mobile Optimization
We could stop here, but I don’t think the end-result works incredibly well on small phone screens. Once you’re happy with how your theme looks with the new Masonry grid on your desktop, check it out on your phone. If you’re not happy about how it looks on your phone, then you will need to do a little work.
I don’t think there is enough room on a phone’s screen for everything we added to our content-masonry template part. Two good solutions available to you are to shorten the excerpt for phones or skip it entirely. Here is an extra function you can add to your theme’s functions.php to do that. Because I don’t think these issues are a problem on tablets, I am using a great plugin Mobble in all of the examples in this section to only make the changes on phones, not tablets. I am also checking to see if Mobble is active before using it and if necessary falling back to the more general mobile detection function wp_is_mobile which is built into WordPress.
As you can see we start by storing the long excerpt length and short excerpt length in variables, since we will be using those values twice and we want to be able to change them from one place if we need to later on. From there we test if we can use Mobble’s is_phone(). If so we set the short excerpt for phones and the long excerpt if we are not. After that we do the same basic thing, but using wp_is_mobile, which will affect all mobile devices ,if is_phone() can’t be used. Hopefully the else part of this function will never be used, but it’s good to have a backup just in case. Once the excerpt length logic is set it just comes down to hooking the function to the excerpt_length filter.
Shortening the excerpt is one option, but we can also do away with it entirely with a simple process. Here is a new version of content-masonry, with the entire excerpt portion ommited on phones:
This time we have are testing to see if we are not on a phone/ mobile device and if so we return the excerpt part of our loop. If we are on a phone/ mobile device we do nothing.
Another thing you might want to do is increase the width of the Masonry items, which reduces the number in a row, on mobile devices. In order to do this, we will add a different inline style to the header based on device detection. Since this function uses wp_add_inline_styles it will be dependent on a specific style sheet. In this case I’m using masonry.css, which you might want, for keeping your masonry styles separate. If you don’t end up using that you can use the handle from another, already registered stylesheet.
This function eneuques the custom stylesheet, and then sets a value for width using what should now be very familiar logic. After that we create the $custom_css variable by passing the value for width into an otherwise regular looking bit of CSS with {$width}. After that we use wp_add_inline_style to tell WordPress to print our inline styles in the header whenever the Masonry stylesheet is being used and then we hook the whole function to wp_enqueue_scripts and we are done.
If you chose to combine your Masonry styles into an existing stylesheet, be sure to use the handle of that style sheet with wp_add_inline_style or your inline styles will not be included. I like to use wp_add_inline_style because I generally wrap the action hook for enqueueing Masonry in a conditional so it only gets added when needed. For example if I am only using Masonry on my blog index and archive pages I would do this:
These last few examples should open up some other ideas in your brain. For example, you could use similar logic to skip Masonry altogether on a mobile device. Also wp_add_inline_style() is a lesser used, yet very helpful function as it allows you to programmatically set different styles based on any type of conditional. It can allow you to radically change the style of any element based on not only device detection, but the changes could also be based on which template is being used, or even if the user is logged in or not.
I hope you see these different changes I am making as an opportunity to get creative. Masonry and similar cascading grid systems have been popular for awhile now, so its time for some new twists on this popular idea. Show us in the comments what cool ways you’ve come up with for using Masonry in a WordPress theme.
A multi-purpose WordPress guy, Josh Pollock writes about WordPress, does theme development, serves as the community manager for the Pods Framework and advocates open source solutions for sustainable design.
To leave a comment please visit How to Use Masonry to Add Pinterest Style Post Grid in WordPress on WPBeginner.