Some themes are more complicated than others with regards to implementing infinite scroll on single post templates.
To help you get started, we’re compiling a library of single.php examples for some popular WordPress themes and frameworks.
GeneratePress is a free WordPress theme that focuses on speed and usability.
Out of the box, the GeneratePress single.php template is pretty close to what we need. All that is required is to wrap the #primary div and add the Ajax Load More code as described in the Single Posts Implementation Guide.
single.php
<?php/** * The Template for displaying all single posts. * * @package GeneratePress */if ( !defined('ABSPATH') ) {exit; // Exit if accessed directly.}get_header(); ?><divid="alm-post-wrap"><divid="primary"<?phpgenerate_do_element_classes('content'); ?>><mainid="main"<?phpgenerate_do_element_classes('main'); ?>><?php/** * generate_before_main_content hook. * * @since 0.1 */do_action('generate_before_main_content');while ( have_posts() ) :the_post();get_template_part('content','single');// If comments are open or we have at least one comment, load up the comment template.if ( comments_open() ||'0'!=get_comments_number() ) :/** * generate_before_comments_container hook. * * @since 2.1 */do_action('generate_before_comments_container');?><divclass="comments-area"><?phpcomments_template(); ?></div><?phpendif;endwhile;/** * generate_after_main_content hook. * * @since 0.1 */do_action('generate_after_main_content');?></main><!--#main --></div><!--#primary --><?php/** * generate_after_primary_content_area hook. * * @since 2.0 */do_action('generate_after_primary_content_area');generate_construct_sidebars();?></div><style>/* Inline style to help with CSS float issues */.alm-single-post{ overflow: hidden;}</style><?phpif( function_exists('alm_render') ){// Ajax Load More $args = ['single_post'=>'true','single_post_id'=>get_the_ID(),'single_post_target'=>'#alm-post-wrap','post_type'=>'post','pause_override'=>'true', ];alm_render($args);}get_footer(); ?>
PHP
The default Genesis single.php template includes only one function, genesis(). This doesn’t work with Ajax Load More so we need to extend the template to include the default Genesis actions, hooks and a wrapping div element.
Below is a modified single.php Genesis template developed specifically for implementation with Ajax Load More.
single.php
<?phpget_header(); ?><divid="alm-post-wrap"><?php/** * Fires after the header, before the content sidebar wrap. * * @since 1.0.0 */do_action('genesis_before_content_sidebar_wrap');genesis_markup(['open'=>'<div %s>','context'=>'content-sidebar-wrap',]);/** * Fires before the content, after the content sidebar wrap opening markup. * * @since 1.0.0 */do_action('genesis_before_content');genesis_markup(['open'=>'<main %s>','context'=>'content',]);/** * Fires before the loop hook, after the main content opening markup. * * @since 1.0.0 */do_action('genesis_before_loop');/** * Fires to display the loop contents. * * @since 1.1.0 */do_action('genesis_loop');/** * Fires after the loop hook, before the main content closing markup. * * @since 1.0.0 */do_action('genesis_after_loop');genesis_markup(['close'=>'</main>',// End .content.'context'=>'content',]);/** * Fires after the content, before the main content sidebar wrap closing markup. * * @since 1.0.0 */do_action('genesis_after_content');genesis_markup(['close'=>'</div>','context'=>'content-sidebar-wrap',]);/** * Fires before the footer, after the content sidebar wrap. * * @since 1.0.0 */do_action('genesis_after_content_sidebar_wrap');?></div><style>/* Inline style to help with CSS float issues */#alm-post-wrap{display:block;overflow:hidden;}.alm-single-post { overflow: hidden;} </style><?phpif( function_exists('alm_render') ){// Ajax Load More $args = ['single_post'=>'true','single_post_id'=>get_the_ID(),'single_post_target'=>'#alm-post-wrap','single_post_order'=>'previous','post_type'=>'post','pause_override'=>'true', ]; alm_render($args);}get_footer(); ?>
PHP
Note: You should always create a Child Theme before modifying core theme templates.
Filter Hooks
alm_single_posts_use_rest_api
This filter will disable the new REST API endpoint introduced in Single Posts v1.8 and fallback to using admin-ajax.php.
The almSinglePostsLoaded() callback is dispatched after Single Posts has completed its initial setup routine on page load.
custom.js
window.almSinglePostsLoaded=function (alm) { console.log( 'ALM Single Posts Loaded' );}
JavaScript
Custom Elements
Quite often, WordPress posts and pages include CSS and JS that are generated specifically for the current post — especially when using page builders or the block editor.
This can create issues when full articles are loaded via Ajax, because only a portion of the page is rendered on screen. As a result, some post-specific CSS or JS may be missing, leading to display or functionality problems.
To address this, the Single Posts add-on includes a feature that automatically detects and pulls any missing CSS and JS into the Ajax-loaded content.
The almSinglePostsCustomElements function provides functionality to specify an array of CSS and JS scripts to load with each article.
The code below instructs the plugin to look for enqueued CSS with the ID my-theme-inline-styles-css each time an article is loaded via Ajax. If the file is found, the CSS will be included with the loaded content, helping prevent any potential display issues.
Below are common questions regarding the Single Posts add-on. If you have a question and don’t see an answer here, please visit the support page and submit your request.
When using Single Posts the pause parameter is automatically set to true, this stops ALM from loading posts on initial page load. The enable scrolling to trigger an Ajax load you need to set pause_override to true.
Example Shortcode[ajax_load_more single_post="true" single_post_target="#post-wrapper" pause_override="true"]
The following code will render content only when loaded via the single post Ajax request.
single.php
if ( isset($_GET) && $_GET[ 'alm_page'] ) ) {echo'<p>I am only displayed when loaded via Ajax</p>';}
PHP
This is possible because Ajax Load More appends querystring parameters to each request for identification purposes.
If you are having trouble displaying your comments template on the posts loaded via Ajax try adding the following $withcomments code above the call your function call to comments_template().
single.php
<?php// Display comments template in Ajax requestglobal $withcomments;$withcomments =true;comments_template();?>
PHP
Any content element that requires JavaScript and has been loaded dynamically (with Ajax) will most likely need to be initiated after a successful Ajax request.
Examples of content that may require JavaScript initiation are:
Social sharing plugins
Facebook Comments
Disqus Comments
Slideshows
Lightbox Galleries
etc…
Have a look at the almComplete() callback function. This callback is triggered after every successful Ajax Load More query and will allow you initiate functionality as content is loaded.
If shortcodes are rendering as static text and not parsing in ajax loaded posts you may need to run a filter in your repeater template on the_content() function.
Visual Composer users are required to execute WPBMap::addAllMappedShortcodes() prior to calling the_content() in an Ajax requests – see the example below:
Yes, but please be aware that if you set a single_post_taxonomy value in the shortcode and the current post has multiple terms assigned, Ajax Load More will look for posts where ANY of the assigned terms are present.
Note: Setting a primary category or term does not affect a post query – this is out of the box WP functionality that cannot be adjusted.
This issue can arise if you have floated elements in your repeater template.
For example, your main post container has a float: left; CSS property assigned – this may cause the positioning of the load more button to become unreliable and cause posts and URLs to update prematurely.
A solution to this problem is to ensure your floated elements are always cleared by assigning the following CSS to the .alm-single-post container.
.alm-single-post{ overflow: hidden; }
This happens in some themes and frameworks because of the way the templates have been structured. To fix this issue add the following code snippet to the start of the Repeater Template.
single.php
<article><?phpglobal $more; $more =true;// The rest of your template goes here!// the_content(); etc.?></article>