how to add masonry and infinite scroll to a tumblr theme
Hi, welcome. If you’re here, it’s because you want to add either Masonry, Infinite Scroll or both to your custom Tumblr theme.
Heads up, this guide requires some familiarity with HTML, CSS and Javascript as you will be editing your current theme and since all themes are different, I can't give step-by-step instructions on how to edit your exact theme.
Also, this post is best viewed on my desktop theme. Blame Tumblr for not supporting Markdown properly.
OVERVIEW
Alright, so what are we even adding? Basically, Masonry is used to display your posts in a nicely laid out grid, even if they're all different sizes. You tell it what your posts are, what you want them to fit into and it'll come up with a nice grid layout for you. Infinite Scroll is used to... infinitely scroll through posts with having to go to another page. It’s the endless scrolling of your Twitter/Instagram/whatever feed.
Now maybe you’ve already got one or the other in your theme and you’re looking to add the other one. Sounds pretty simple, yeah? It kind of is. The trouble is that Masonry and Infinite Scroll interact with each other. When you’re using Infinite Scroll, whenever you scroll down and load more posts, Masonry needs to check whether your post layout is still okay and correct it if it isn't.
PLUGINS
For the sake of this guide not getting too confusing and because they integrate so easily together, we’ll ONLY be using David DeSandro's Masonry and Infinite Scroll Javascript plugins. If you’ve got different versions of these plugins, remove them now as they may cause issues.
First, we need to add the plugins to your theme’s head:
<script src="https://unpkg.com/masonry-layout@4/dist/masonry.pkgd.min.js"></script><script src="https://unpkg.com/infinite-scroll@4/dist/infinite-scroll.pkgd.min.js"></script>
HTML
To get Masonry working, we need to know what your posts are and the container that they're in. Give your posts a class (e.g. .post) and your container an id (e.g. #posts). We can also specify additional options, such as column width and spacing between the posts. We want the layout to be responsive, so by following the example code Masonry provides, we'll create post-sizer and gutter-sizer.
To add Infinite Scroll, we need to know what the posts are (same as Masonry) and where to get the new content from - this will be the next page of posts on your blog. Tumblr lets us get that easily using pagination variables. Make sure you give the next page a class (e.g. .pagination__next), since this is where we'll be loading new posts from.
Your HTML might look something like this:
<div id="posts"> <div id="post-sizer"></div> <div id="gutter-sizer"></div> {block:Posts} <div class="post" id="{PostID}"> <div class="post-content"> {block:Text} {/block:Text} </div> </div> {/block:Posts} </div> <p id="footer"> {block:PreviousPage} <a href="{PreviousPage}">« Previous</a> {/block:PreviousPage} {block:NextPage} <a href="{NextPage}" class="pagination__next">Next »</a> {/block:NextPage} <a href="/archive">Archive</a> </p>
CSS
For the styling, we want the layout to be responsive so we'll set post-sizer and gutter-sizer to have a % width. For the rest of the styling, we'll use some of Masonry's example code again.
Your CSS might look something like this:
* { box-sizing: border-box; } #posts { width: 800px; } #posts:after { content: ''; display: block; clear: both; } #post-sizer, .post { width: 32.66%; } #gutter-sizer { width: 1%; } .post { background-color: lightgrey; margin-bottom: 10px; } .post-content { width: 100%; padding: 10px; float: left; }
JAVASCRIPT
In your theme's head, we can create a new script and set up Masonry inside it like this:
<script> window.onload = function() { var elem = document.getElementById('posts'); var msnry = new Masonry(elem, { itemSelector: '.post', percentPosition: true, columnWidth: '#post-sizer', gutter: '#gutter-sizer' }); } </script>
Then to actually get Masonry to generate a layout, we need to call it like this:
msnry.layout();
Usually, that's all you really need for Masonry but for Tumblr posts, any media embeds might take a bit of time to load. For example, Instagram embeds get taller when they're fully loaded (or at least they used to) and this can screw up the layout of your posts. To deal with this, you can add an observer that checks for any changes with media embeds and calculates a new layout if needed:
const embedObserver = new MutationObserver((m, o) => { msnry.layout(); }); embedObserver.observe(document, { childList: true, subtree: true });
Then finally, we need to set up Infinite Scroll. Remember, we're using the same posts that Masonry is changing. Since this plugin is made by the same guy who wrote Masonry, we can integrate it easily using outlayer:
let infScroll = new InfiniteScroll(elem, { path: '.pagination__next', append: '.post', outlayer: msnry });
Every time it loads a new page, it'll update the URL in your address bar. If you want to turn that off, you can add a new line to the previous codeblock, setting history to false:
let infScroll = new InfiniteScroll(elem, { path: '.pagination__next', append: '.post', history: false, outlayer: msnry });
And that should be it! The whole script should be something like this:
<script> window.onload = function() { // INITIALISE MASONRY var elem = document.getElementById('posts'); var msnry = new Masonry(elem, { itemSelector: '.post', percentPosition: true, columnWidth: '#post-sizer', gutter: '#gutter-sizer' }); // CALL MASONRY LAYOUT msnry.layout(); // CALL MASONRY LAYOUT ON EMBED LOAD const embedObserver = new MutationObserver((m, o) => { msnry.layout(); }); embedObserver.observe(document, { childList: true, subtree: true }); // INITIALISE INFINITE SCROLL let infScroll = new InfiniteScroll(elem, { path: '.pagination__next', append: '.post', history: false, outlayer: msnry }); } </script>
FINALLY...
Do keep in mind that your theme code will be different to this, so it's not a case of just copying and pasting everything directly. Remember to remove any old Masonry or Infinite Scroll plugins you already have. Your class and id names will probably be different and you may need to add certain HTML elements if you're missing them. You'll almost certainly need to tweak the styling too.
Feel free to shoot me a message if you need help or want to heckle me about the guide being outdated.















