JustinWDev of Archived Theme Support
5/27/2015 - 8:23 AM

Add infinite scrolling to collection pages. Tested in #Pop theme.

Add infinite scrolling to collection pages. Tested in #Pop theme.

The work was completed a moment ago.

You can go to this page to see the infinite scrolling in action — that page contains all products in your store.

Start scrolling down. The page will progressively, as you scroll down, load all items in your store. Keep an eye on the vertical scrolling bar on the right. A page-full of items is loaded at a time, only when a threshold is met. The scrolling cursor will appear all the way down, and then, it will move up again, after a page of items has been loaded, and that process will repeat itself for each page loaded.

For usability, pagination links are kept at the top of a page, should someone still want to use those. It's highly recommended to have them still available also for search engines. Search engines don't load content with JavaScript, they don't scroll down the page, and will need links to your paginated content. Those pagination links are hidden when the infinite scrolling is in effect.

Please have a look at your convenience and let me know how it goes!

Infinite scrolling is a technique where additional content for a web page is appended dynamically to the bottom of the page as the user approaches the end of the content.

In Shopify, that translates to rows of products from page 2 then page 3 and so on getting loaded and appended with Ajax as you scroll down page 1 of your collection.

  1. Upload this plugin from Paul Irish to your theme assets. You can also create a blank asset on the Template Editor page, name it jquery.infinitescroll.min.js, and copy+paste the code from Github to it.

  2. In theme.liquid before the closing /body> tag, paste this code — then edit the option values so that they work with your theme! The section that follows will hold your hand through that.

    {% if template contains 'collection' %}
    
    {{ 'jquery.infinitescroll.min.js' | asset_url | script_tag }}
    
    <script>
     $('.product-grid').infinitescroll({
       navSelector  : ".pagination-custom",
       nextSelector : ".pagination-custom .next-page",
       itemSelector : ".product-grid .product-grid-item",
       loading: {
         img         : {{ 'spinner.gif' | asset_url | json }},
         msgText     : 'Loading more products...',
         finishedMsg : 'There are no more products in this collection.'
       },
       pathParse:function(path,nextPage){
         return path.match(/^(.*page=)[0-9]*(&.*)?$/).splice(1);
       }
     });
    </script>
    
    {% endif %}
    

    Read through all this

    • You call infinitescroll on the element that directly contains your {% for product in collection.products %} loop in collection.liquid. In Timber themes, that element usually has a class set to .grid-uniform. It might be safer to add a class to that element and use it if you're unfamiliar with the rest of the markup used on the collection page. You only want to call infinitescroll on the element you will be appending product boxes to. You can even use an id. In the Pop theme, you have what's below, so you can use .grid-uniform or .product-grid:

    • The navSelector must be the selector for the containing element of your pagination links. Once the entire collection has been loaded on the page, the plugin will hide the pagination links at the top of the page (where you'll copy them in a moment), hence the need to specify that selector.

    • The nextSelector must select the anchor element which points at the next page in the collection. In most Timber themes, that anchor element has no class, and no id, so you'll need to add a class. I've used .next-page as selector, so in the Pop theme, I had to edit the pagination-custom.liquid snippet to add that class to the next page anchor element. Go ahead and add that class, if and as needed, in your theme.

    • The itemSelector must select the parent element of an individual product box (one product) on collection pages. In most Timber-based themes, that box does not have a special class identifier, so you may need to add one, then use it here. It's super important that no other element on the page match that selector, because the plugin will go on fetching a new — empty — page if a fetched page still contains any element that matches the selector. When the inifinite scrolling plugin fetches a page that contains nothing matching the itemSelector it will finally stop nagging the server. Special gotcha: in many newer themes, an empty collection page will show onboarding placeholder products, so you need a selector that ignores those, does not match those, so it is safer to add an additional class to your element and target it. In the Pop theme, I added a product-grid-item class to the product box, and used it in my scrolling options:

    • The loading property contains all the text and a link to a loading GIF you may or may not see depending on how fast you scroll down the page, and how slow your Internet connection is. If you scroll down frantically you may see a loader pop up.

  3. Upload an animated spinner.gif image to your theme assets.

    I like this one:

    http://dictionary.cambridge.org/utilities/2015-07-08-1042/external/images/spinner.gif

  4. In collection.liquid, move the code block for your pagination above the element that contains the product boxes. In other words, do show pagination links, but rather than having them at the bottom of the page, show them at the top of your products. Don't remove the pagination links from the collection page! If you really don't want them, hide them with CSS.

  5. If you scroll down really quickly, and the server is unable to catch up and give you products to see right away, the plugin will show 'Loading more products...' with the loader GIF. That text adds an element to the DOM that is a sibling of the product boxes, and, so, alas, that will mess up the CSS clearing applied by Timber, so you need a bit of CSS to keep the grid clearing bullet-proof.

    For example, if your theme uses large--one-third medium--one-third for the product boxes, you'll need to fix the CSS clearing as followed:

    #infscr-loading {
      text-align: center;
    }
    
    @include at-query ($min, $large) {
      #infscr-loading ~ .large--one-third:nth-child(3n+1) { clear: none !important }
      #infscr-loading ~ .large--one-third:nth-child(3n+2) { clear: both !important }
    }
    
    @include at-query (null, $small, $medium) {
      #infscr-loading ~ .medium--one-third:nth-child(3n+1) { clear: none !important }
      #infscr-loading ~ .medium--one-third:nth-child(3n+2) { clear: both !important }
    }
    

    If your theme uses medium-down--one-half large--one-quarter for the product boxes, you'll need to fix the CSS clearing as followed:

    #infscr-loading {
      text-align: center;
    }
    
    @include at-query ($min, $large) {
      #infscr-loading ~ .large--one-quarter:nth-child(4n+1) { clear: none !important }
      #infscr-loading ~ .large--one-quarter:nth-child(4n+2) { clear: both !important }
    }
    
    @include at-query ($max, $medium) {
      #infscr-loading ~ .medium-down--one-half:nth-child(2n+1) { clear: none !important }
      #infscr-loading ~ .medium-down--one-half:nth-child(2n+2) { clear: both !important }
    }