Answers.Body: <p>Here's a cut-down version of what I'm using on <a href="https://cld.agency/showcase" rel="nofollow noreferrer">https://cld.agency/showcase</a></p>
  <p>The quick example below uses jQuery, but I have a more complete updated version using vanilla JS here: <a href="https://github.com/cld-agency/craftwind-boilerplate/blob/craft-4/templates/_listings/default.twig" rel="nofollow noreferrer">https://github.com/cld-agency/craftwind-boilerplate/blob/craft-4/templates/_listings/default.twig</a></p>
  <pre><code>{% set theLayout = craft.app.request.isAjax and not craft.app.request.isLivePreview ? '_ajaxLayout' : '_layout' %}
  {% extends theLayout %}
  
  {% set entries = craft.entries.section('news').limit(12) %}
  {% paginate entries as pageInfo, pageEntries %}
  
  {# =============================================================================== #}
  
  {% block content %}     
      &lt;h1&gt;News&lt;/h1&gt;
      &lt;p&gt;Introduction&lt;/p&gt;
      &lt;ul class=&quot;js-ajaxPagination&quot;&gt;      
          {% for card in pageEntries %}
              &lt;li&gt;{% include '_partials/card'  %}&lt;/li&gt;
          {% endfor %}
      &lt;/ul&gt;
      {# allow no-js/googlebot fallback with a regular href to the next page... #}
      &lt;p&gt;&lt;a class=&quot;js-loadMore&quot; href=&quot;{{ '/' ~ craft.app.request.pathInfo ~ '/p' ~ (pageInfo.currentPage + 1) }}&quot;&gt;Load more&lt;/a&gt;&lt;/p&gt;
  {% endblock %}
  
  {# =============================================================================== #}
  
  {% block ajaxContent %}
      {% for card in pageEntries %}
          &lt;li&gt;{% include '_partials/card' %}&lt;/li&gt;
      {% endfor %}
  {% endblock %}
  
  {# ======================================
  AJAX PAGINATION SCRIPT
  ========================================= #}
  
  {% if pageInfo is defined and pageInfo.total &gt; 12 %}
      {% js %}
          var currentPage = 1;
          var perPage = 12;
          var count = perPage;
          $('.js-loadMore').click(function(e){
              e.preventDefault();
              if({{ pageInfo.total }} &gt; count){
                  $.ajax({
                      url: $(this).attr('href'),
                  }).done(function(data) {
                      var $new = $('.js-ajaxPagination').append(data);
                      var $button = $('.js-loadMore');
                      // increment the counters
                      count = count + perPage;
                      currentPage++;
                      $button.show().attr('href', '/{{ craft.app.request.pathInfo }}/p' + (currentPage + 1));
                      if({{ pageInfo.total }} &lt;= count){
                          $button.remove();
                      }
                  });
              }
          });
      {% endjs %}
  {% endif %}
  </code></pre>
  <p>So the trick is forking which template gets extended depending on whether it's an ajax request. Your _ajaxLayout template would be as simple as just:</p>
  <p><code>{{ block('ajaxContent') }}</code></p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-07-07T13:23:54.673Z
Answers.Text: Thanks for the answer, looks great on your site! I'm having a bit of trouble getting it to work on my end. Would it be possible to see where my code would plug into this system? (Sorry, still learning :) )
Answers.UserDisplayName: Justin Kendall
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-07-07T13:35:06.780Z
Answers.Text: It's impossible to say without knowing your exact setup, and there are lots of ways of achieving the same result... My example assumes that you have a global layout template called `_layout` and that that template contains a  `{{ endBody() }}` tag to accept the injected js and a `content` block to output the content.
Answers.UserDisplayName: James Smith
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-07-09T13:29:31.940Z
Answers.Text: Ok, I'm running into some snags. I don't think I have the structure for this set up correctly. My site is currently set up with my header/footer in a file called `_main`  then all of my pages extends `_main` via `{% block content%}`. I'm currently trying to do this "More Posts" area in its own file `_loadMore` which I then `include` in my page. Right now it is doing some weird stuff like having multiple buttons and messing up the layout. And when I click the button, it literally duplicates the entire page in the area. So, I'm a bit confused on how you're using `theLayout` with your ajax
Answers.UserDisplayName: Justin Kendall
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-07-09T13:39:44.337Z
Answers.Text: Ok, I just realized that the funky layout stuff, was an error on my part. But it is still duplicating the page when I click my "Load More" button
Answers.UserDisplayName: Justin Kendall
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-07-09T13:51:35.060Z
Answers.Text: What is in your ajaxLayout template? (or whatever you named it)
Answers.UserDisplayName: James Smith
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-07-09T13:53:34.627Z
Answers.Text: `{{ block('ajaxContent') }}` like you said. but that is one thing I'm confused about. How are you linking to it/where do I put it?
Answers.UserDisplayName: Justin Kendall
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-07-09T14:34:33.680Z
Answers.Text: So your listings template extends either your main layout template (yours is called _main), or this ajaxLayout template depending on whether it's an ajax request (see the very first line in my example). If it is an ajax request, it'll output the block called 'ajaxContent', if not it'll output the block called 'content'.
Answers.UserDisplayName: James Smith
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-07-09T15:03:40.673Z
Answers.Text: Ok, I just edited my question to include the code I have utilizing your method. It is now giving me an internal server error.
Answers.UserDisplayName: Justin Kendall
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-07-09T15:14:04.797Z
Answers.Text: Right I see - you're trying to `extend` in an include, and that's never going to work... you need to get all this stuff into your `_page` template. It needs: a dynamic `extends` statement, a `content` block, and an `ajaxContent` block. If you want to abstract to an include, do it after the basic version is working.
Answers.UserDisplayName: James Smith
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-07-09T15:18:32.487Z
Answers.Text: Let us [continue this discussion in chat](https://chat.stackexchange.com/rooms/110408/discussion-between-a-b-creative-and-james-smith).
Answers.UserDisplayName: Justin Kendall
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-07-07T12:40:08.947Z
Answers.LastActivityDate: 2023-02-24T09:11:54.090Z
Answers.LastEditDate: 2023-02-24T09:11:54.090Z
Answers.UserDisplayName: James Smith
Answers.Body: <p>The <a href="https://putyourlightson.com/plugins/sprig" rel="noreferrer">Sprig plugin</a> will save you a lot of trouble, and dynamically loading more entries is a perfect use-case for it. If you prefer to use jQuery, then by all means do so, but keep in mind that it is just as much of a dependency as Sprig. For the record, Sprig has been widely adopted and at the time of writing has over 4,700 active installs in the <a href="https://plugins.craftcms.com/sprig" rel="noreferrer">plugin store</a>.</p>
  <p>Here is the <a href="https://putyourlightson.com/sprig/cookbook#load-more" rel="noreferrer">load more recipe</a> component, adapted for your markup.</p>
  <pre><code>{% set limit = 10 %}
  {% set offset = offset ?? 0 %}
  
  {% set entryQuery = craft.entries.section('aBetterPost').offset(offset).limit(limit) %}
  {% set entries = entryQuery.all() %}
  
  {% for entry in entries %}
      &lt;a href=&quot;{{ entry.getUrl }}&quot; class=&quot;more-post&quot;&gt;
          &lt;div class=&quot;more-post-img-wrap&quot;&gt;
              {% set featuredImage = entry.featuredImage.one() %}
              &lt;img src=&quot;{{ featuredImage.getUrl }}&quot; class=&quot;more-post-img&quot;&gt;
              &lt;div class=&quot;red-overlay&quot;&gt;&lt;/div&gt;
          &lt;/div&gt;
          &lt;div class=&quot;more-post-content&quot;&gt;
              &lt;div class=&quot;more-post-title&quot;&gt;
                  &lt;h3&gt;{{ entry.title }}&lt;/h3&gt;
              &lt;/div&gt;
              &lt;div class=&quot;next-icon&quot;&gt;
                  &lt;i class=&quot;fas fa-chevron-right&quot;&gt;&lt;/i&gt;
              &lt;/div&gt;
          &lt;/div&gt;
      &lt;/a&gt;
  {% endfor %}
  
  {# If the total entry count is greater than the number that has been displayed #}
  {% if entryQuery.count() &gt; offset + entries|length %}
      &lt;div id=&quot;more-posts&quot;&gt;
          &lt;div class=&quot;load-button-wrap&quot;&gt;
              &lt;a sprig s-val:offset=&quot;{{ offset + limit }}&quot; s-target=&quot;#more-posts&quot; s-swap=&quot;outerHTML&quot; href=&quot;#&quot;&gt;
                  &lt;div class=&quot;load-button&quot;&gt;
                      &lt;p&gt;Load More&lt;/p&gt;
                  &lt;/div&gt;
              &lt;/a&gt;
          &lt;/div&gt;
      &lt;/div&gt;
  {% endif %}
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-08T15:54:46.313Z
Answers.Text: Thanks for the answer! I had started using Sprig shortly after this question was posted, and I have loved it! Great plugin!
Answers.UserDisplayName: Justin Kendall
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-12-26T10:28:09.277Z
Answers.LastActivityDate: 2021-12-26T10:28:09.277Z
Answers.UserDisplayName: Ben Croker
Body: <p>I am trying to make my entry loop have a load more button, and not sure how to do it. I tried the method from <a href="http://craftsnippets.com/articles/infinite-scrolling-and-lazy-loading-with-craft-cms" rel="nofollow noreferrer">http://craftsnippets.com/articles/infinite-scrolling-and-lazy-loading-with-craft-cms</a> but I could not get it to work.</p>
  <p>Below is the code for my entry loop and &quot;Load More&quot; button. What would be the easiest way to make the &quot;Load More&quot; button functional?</p>
  <pre><code>            &lt;div class=&quot;more-posts-wrap&quot;&gt;
  
                  {% set moreABetterPost = craft.entries.section('aBetterPost').all() %}
                  {% for entry in moreABetterPost %}
                  &lt;a href=&quot;{{ entry.getUrl }}&quot; class=&quot;more-post&quot;&gt;
                      &lt;div class=&quot;more-post-img-wrap&quot;&gt;
                          {% set featuredImage = entry.featuredImage.one() %}
                          &lt;img src=&quot;{{ featuredImage.getUrl }}&quot; class=&quot;more-post-img&quot;&gt;
                          &lt;div class=&quot;red-overlay&quot;&gt;&lt;/div&gt;
                      &lt;/div&gt;
                      &lt;div class=&quot;more-post-content&quot;&gt;
                          &lt;div class=&quot;more-post-title&quot;&gt;
                              &lt;h3&gt;{{ entry.title }}&lt;/h3&gt;
                          &lt;/div&gt;
                          &lt;div class=&quot;next-icon&quot;&gt;
                              &lt;i class=&quot;fas fa-chevron-right&quot;&gt;&lt;/i&gt;
                          &lt;/div&gt;
                      &lt;/div&gt;
                  &lt;/a&gt;
                  {% endfor %}
  
              &lt;/div&gt;
  
              &lt;div class=&quot;load-button-wrap&quot;&gt;
                  &lt;a href=&quot;#&quot;&gt;
                      &lt;div class=&quot;load-button&quot;&gt;
                          &lt;p&gt;Load More&lt;/p&gt;
                      &lt;/div&gt;
                  &lt;/a&gt;
              &lt;/div&gt;
  </code></pre>
  <p><strong>EDIT:</strong> Clarifying the structure of my site.</p>
  <pre><code>{# _main.twig #}
  Header Stuff
  Header Stuff
  ...
  {% block content %}
  {# All of my pages exist in here by extending _main.twig #}
  Page Stuff
  Page Stuff
  Page Stuff
  ...
  LOAD MORE ENTRIES AREA
  {% endblock %}
  Footer Stuff
  Footer Stuff
  Footer Stuff
  ...
  {# End of _main.twig #}
  </code></pre>
  <p><strong>EDIT 2:</strong> Showing the code that's not working in regards to James Smith's Answer.</p>
  <p><strong>_loadMore.twig</strong></p>
  <pre><code>{% set theLayout = craft.app.request.isAjax and not craft.app.request.isLivePreview ? '_ajaxLayout' : '_main' %}
  {% extends theLayout %}
  
  &lt;section&gt;
      &lt;div class=&quot;more-posts-section&quot;&gt;
          &lt;div class=&quot;section-header&quot;&gt;
              &lt;h2&gt;More Posts in &lt;span&gt;{{ category.title }}&lt;/span&gt;&lt;/h2&gt;
          &lt;/div&gt;
  
          {% set entries = craft.entries.section('aBetterPost').limit(6) %}
          {% paginate entries as pageInfo, pageEntries %}
  
  
          {% block content %}
          &lt;div class=&quot;more-posts-wrap-border&quot;&gt;
              &lt;div class=&quot;more-posts-wrap js-ajaxPagination&quot;&gt;
                  {% for entry in aBetterPost%}
                    {% include '_layouts/_post' %}
                  {% endfor %}
              &lt;/div&gt;
          &lt;/div&gt;
          {% endblock %}
          
          &lt;div class=&quot;load-button-wrap&quot;&gt;
              &lt;a href=&quot;{{ '/' ~ craft.app.request.pathInfo ~ '/p' ~ (pageInfo.currentPage + 1) }}&quot; class=&quot;load-button js-loadMore&quot;&gt;{{'load more'|t}}&lt;/a&gt;
          &lt;/div&gt;
  
          {% block ajaxContent %}
              {% for entry in aBetterPost%}
                {% include '_layouts/_post' %}
              {% endfor %}
          {% endblock %}
      &lt;/div&gt;
  &lt;/section&gt;
  
  {# ======================================
  AJAX PAGINATION SCRIPT
  ========================================= #}
  
  {% if pageInfo is defined and pageInfo.total &gt; 6 %}
      {% js %}
          var currentPage = 1;
          var perPage = 6;
          var count = perPage;
          $('.js-loadMore').click(function(e){
              e.preventDefault();
              if({{ pageInfo.total }} &gt; count){
                  $.ajax({
                      url: $(this).attr('href'),
                  }).done(function(data) {
                      var $new = $('.js-ajaxPagination').append(data);
                      var $button = $('.js-loadMore');
                      // increment the counters
                      count = count + perPage;
                      currentPage++;
                      $button.show().attr('href', '/{{ craft.app.request.pathInfo }}/p' + (currentPage + 1));
                      if({{ pageInfo.total }} &lt;= count){
                          $button.remove();
                      }
                  });
              }
          });
      {% endjs %}
  {% endif %}
  </code></pre>
  <p><strong>_page.twig</strong></p>
  <pre><code>{% extends &quot;_layouts/_main&quot; %}
  {% block content %}
     {# Other Page Stuff#}
     {# Other Page Stuff#}
     {% include '_layouts/_loadMore' %}
  {% endblock %}
  </code></pre>
  
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2020-07-07T01:04:38.587Z
Comments.Text: Have you set up element api endpoint as described in article and added js code to website that handle ajax requests? Also, alternative to using solution described in my article, would be using sprig plugin: https://putyourlightson.com/sprig-cookbook#load-more
Comments.UserDisplayName: Piotr Pogorzelski
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2020-07-07T09:22:05.320Z
Comments.Text: Why bother with the added complexity of using the Element API or adding and learning yet another abstraction like Sprig? Just call up your same listing template and have two Twig blocks - one for Ajax requests and one for regular requests. Keep it simple!
Comments.UserDisplayName: James Smith
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2020-07-07T12:19:14.830Z
Comments.Text: @piotrpog I added the JS, but I think the API stuff is where I got hung up. That Sprig plugin might be a good option, but I'm always a bit leery about non-first-party plugins with keeping up with Craft updates and such.
Comments.UserDisplayName: Justin Kendall
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2020-07-07T12:21:14.487Z
Comments.Text: @JamesSmith I am definitely not married to the method that I tried. If there is an easier/better way to do it, I'm all ears! Could you explain the process you mentioned a little more?
Comments.UserDisplayName: Justin Kendall
Tags: <craft3><ajax><forloop><javascript>
Title: Load More Entries Button
ThreadText: # Load More Entries Button
  
  (Asked by: username_0 on 2020-07-06)
  
  I am trying to make my entry loop have a load more button, and not sure how to do it. I tried the method from <http://craftsnippets.com/articles/infinite-scrolling-and-lazy-loading-with-craft-cms> but I could not get it to work.
  
  Below is the code for my entry loop and "Load More" button. What would be the easiest way to make the "Load More" button functional?
  
  ```
              <div class="more-posts-wrap">
  
                  {% set moreABetterPost = craft.entries.section('aBetterPost').all() %}
                  {% for entry in moreABetterPost %}
                  <a href="{{ entry.getUrl }}" class="more-post">
                      <div class="more-post-img-wrap">
                          {% set featuredImage = entry.featuredImage.one() %}
                          <img src="{{ featuredImage.getUrl }}" class="more-post-img">
                          <div class="red-overlay"></div>
                      </div>
                      <div class="more-post-content">
                          <div class="more-post-title">
                              <h3>{{ entry.title }}</h3>
                          </div>
                          <div class="next-icon">
                              <i class="fas fa-chevron-right"></i>
                          </div>
                      </div>
                  </a>
                  {% endfor %}
  
              </div>
  
              <div class="load-button-wrap">
                  <a href="#">
                      <div class="load-button">
                          <p>Load More</p>
                      </div>
                  </a>
              </div>
  
  ```
  
  **EDIT:** Clarifying the structure of my site.
  
  ```
  {# _main.twig #}
  Header Stuff
  Header Stuff
  ...
  {% block content %}
  {# All of my pages exist in here by extending _main.twig #}
  Page Stuff
  Page Stuff
  Page Stuff
  ...
  LOAD MORE ENTRIES AREA
  {% endblock %}
  Footer Stuff
  Footer Stuff
  Footer Stuff
  ...
  {# End of _main.twig #}
  
  ```
  
  **EDIT 2:** Showing the code that's not working in regards to username_2's Answer.
  
  **\_loadMore.twig**
  
  ```
  {% set theLayout = craft.app.request.isAjax and not craft.app.request.isLivePreview ? '_ajaxLayout' : '_main' %}
  {% extends theLayout %}
  
  <section>
      <div class="more-posts-section">
          <div class="section-header">
              <h2>More Posts in <span>{{ category.title }}</span></h2>
          </div>
  
          {% set entries = craft.entries.section('aBetterPost').limit(6) %}
          {% paginate entries as pageInfo, pageEntries %}
  
          {% block content %}
          <div class="more-posts-wrap-border">
              <div class="more-posts-wrap js-ajaxPagination">
                  {% for entry in aBetterPost%}
                    {% include '_layouts/_post' %}
                  {% endfor %}
              </div>
          </div>
          {% endblock %}
          
          <div class="load-button-wrap">
              <a href="{{ '/' ~ craft.app.request.pathInfo ~ '/p' ~ (pageInfo.currentPage + 1) }}" class="load-button js-loadMore">{{'load more'|t}}</a>
          </div>
  
          {% block ajaxContent %}
              {% for entry in aBetterPost%}
                {% include '_layouts/_post' %}
              {% endfor %}
          {% endblock %}
      </div>
  </section>
  
  {# ======================================
  AJAX PAGINATION SCRIPT
  ========================================= #}
  
  {% if pageInfo is defined and pageInfo.total > 6 %}
      {% js %}
          var currentPage = 1;
          var perPage = 6;
          var count = perPage;
          $('.js-loadMore').click(function(e){
              e.preventDefault();
              if({{ pageInfo.total }} > count){
                  $.ajax({
                      url: $(this).attr('href'),
                  }).done(function(data) {
                      var $new = $('.js-ajaxPagination').append(data);
                      var $button = $('.js-loadMore');
                      // increment the counters
                      count = count + perPage;
                      currentPage++;
                      $button.show().attr('href', '/{{ craft.app.request.pathInfo }}/p' + (currentPage + 1));
                      if({{ pageInfo.total }} <= count){
                          $button.remove();
                      }
                  });
              }
          });
      {% endjs %}
  {% endif %}
  
  ```
  
  **\_page.twig**
  
  ```
  {% extends "_layouts/_main" %}
  {% block content %}
     {# Other Page Stuff#}
     {# Other Page Stuff#}
     {% include '_layouts/_loadMore' %}
  {% endblock %}
  
  ```
  
  **Tags:** craft3, ajax, forloop, javascript
  
  > **Comments:**
  > **username_1**: Have you set up element api endpoint as described in article and added js code to website that handle ajax requests? Also, alternative to using solution described in my article, would be using sprig plugin: https://putyourlightson.com/sprig-cookbook#load-more  
  > **username_2**: Why bother with the added complexity of using the Element API or adding and learning yet another abstraction like Sprig? Just call up your same listing template and have two Twig blocks - one for Ajax requests and one for regular requests. Keep it simple!  
  > **username_0**: @piotrpog I added the JS, but I think the API stuff is where I got hung up. That Sprig plugin might be a good option, but I'm always a bit leery about non-first-party plugins with keeping up with Craft updates and such.  
  > **username_0**: @username_2 I am definitely not married to the method that I tried. If there is an easier/better way to do it, I'm all ears! Could you explain the process you mentioned a little more?  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_3 on 2021-12-26. Score: 6 | Accepted answer
  
  The [Sprig plugin](https://putyourlightson.com/plugins/sprig) will save you a lot of trouble, and dynamically loading more entries is a perfect use-case for it. If you prefer to use jQuery, then by all means do so, but keep in mind that it is just as much of a dependency as Sprig. For the record, Sprig has been widely adopted and at the time of writing has over 4,700 active installs in the [plugin store](https://plugins.craftcms.com/sprig).
  
  Here is the [load more recipe](https://putyourlightson.com/sprig/cookbook#load-more) component, adapted for your markup.
  
  ```
  {% set limit = 10 %}
  {% set offset = offset ?? 0 %}
  
  {% set entryQuery = craft.entries.section('aBetterPost').offset(offset).limit(limit) %}
  {% set entries = entryQuery.all() %}
  
  {% for entry in entries %}
      <a href="{{ entry.getUrl }}" class="more-post">
          <div class="more-post-img-wrap">
              {% set featuredImage = entry.featuredImage.one() %}
              <img src="{{ featuredImage.getUrl }}" class="more-post-img">
              <div class="red-overlay"></div>
          </div>
          <div class="more-post-content">
              <div class="more-post-title">
                  <h3>{{ entry.title }}</h3>
              </div>
              <div class="next-icon">
                  <i class="fas fa-chevron-right"></i>
              </div>
          </div>
      </a>
  {% endfor %}
  
  {# If the total entry count is greater than the number that has been displayed #}
  {% if entryQuery.count() > offset + entries|length %}
      <div id="more-posts">
          <div class="load-button-wrap">
              <a sprig s-val:offset="{{ offset + limit }}" s-target="#more-posts" s-swap="outerHTML" href="#">
                  <div class="load-button">
                      <p>Load More</p>
                  </div>
              </a>
          </div>
      </div>
  {% endif %}
  
  ```
  
  > **Comments:**
  > **username_0**: Thanks for the answer! I had started using Sprig shortly after this question was posted, and I have loved it! Great plugin!  
  
  ---
  
  ### Answer by username_2 on 2020-07-07. Score: 4
  
  Here's a cut-down version of what I'm using on <https://cld.agency/showcase>
  
  The quick example below uses jQuery, but I have a more complete updated version using vanilla JS here: <https://github.com/cld-agency/craftwind-boilerplate/blob/craft-4/templates/_listings/default.twig>
  
  ```
  {% set theLayout = craft.app.request.isAjax and not craft.app.request.isLivePreview ? '_ajaxLayout' : '_layout' %}
  {% extends theLayout %}
  
  {% set entries = craft.entries.section('news').limit(12) %}
  {% paginate entries as pageInfo, pageEntries %}
  
  {# =============================================================================== #}
  
  {% block content %}     
      <h1>News</h1>
      <p>Introduction</p>
      <ul class="js-ajaxPagination">      
          {% for card in pageEntries %}
              <li>{% include '_partials/card'  %}</li>
          {% endfor %}
      </ul>
      {# allow no-js/googlebot fallback with a regular href to the next page... #}
      <p><a class="js-loadMore" href="{{ '/' ~ craft.app.request.pathInfo ~ '/p' ~ (pageInfo.currentPage + 1) }}">Load more</a></p>
  {% endblock %}
  
  {# =============================================================================== #}
  
  {% block ajaxContent %}
      {% for card in pageEntries %}
          <li>{% include '_partials/card' %}</li>
      {% endfor %}
  {% endblock %}
  
  {# ======================================
  AJAX PAGINATION SCRIPT
  ========================================= #}
  
  {% if pageInfo is defined and pageInfo.total > 12 %}
      {% js %}
          var currentPage = 1;
          var perPage = 12;
          var count = perPage;
          $('.js-loadMore').click(function(e){
              e.preventDefault();
              if({{ pageInfo.total }} > count){
                  $.ajax({
                      url: $(this).attr('href'),
                  }).done(function(data) {
                      var $new = $('.js-ajaxPagination').append(data);
                      var $button = $('.js-loadMore');
                      // increment the counters
                      count = count + perPage;
                      currentPage++;
                      $button.show().attr('href', '/{{ craft.app.request.pathInfo }}/p' + (currentPage + 1));
                      if({{ pageInfo.total }} <= count){
                          $button.remove();
                      }
                  });
              }
          });
      {% endjs %}
  {% endif %}
  
  ```
  
  So the trick is forking which template gets extended depending on whether it's an ajax request. Your \_ajaxLayout template would be as simple as just:
  
  `{{ block('ajaxContent') }}`
  
  > **Comments:**
  > **username_0**: Thanks for the answer, looks great on your site! I'm having a bit of trouble getting it to work on my end. Would it be possible to see where my code would plug into this system? (Sorry, still learning :) )  
  > **username_2**: It's impossible to say without knowing your exact setup, and there are lots of ways of achieving the same result... My example assumes that you have a global layout template called `_layout` and that that template contains a  `{{ endBody() }}` tag to accept the injected js and a `content` block to output the content.  
  > **username_0**: Ok, I'm running into some snags. I don't think I have the structure for this set up correctly. My site is currently set up with my header/footer in a file called `_main`  then all of my pages extends `_main` via `{% block content%}`. I'm currently trying to do this "More Posts" area in its own file `_loadMore` which I then `include` in my page. Right now it is doing some weird stuff like having multiple buttons and messing up the layout. And when I click the button, it literally duplicates the entire page in the area. So, I'm a bit confused on how you're using `theLayout` with your ajax  
  > **username_0**: Ok, I just realized that the funky layout stuff, was an error on my part. But it is still duplicating the page when I click my "Load More" button  
  > **username_2**: What is in your ajaxLayout template? (or whatever you named it)  
  > **username_0**: `{{ block('ajaxContent') }}` like you said. but that is one thing I'm confused about. How are you linking to it/where do I put it?  
  > **username_2**: So your listings template extends either your main layout template (yours is called _main), or this ajaxLayout template depending on whether it's an ajax request (see the very first line in my example). If it is an ajax request, it'll output the block called 'ajaxContent', if not it'll output the block called 'content'.  
  > **username_0**: Ok, I just edited my question to include the code I have utilizing your method. It is now giving me an internal server error.  
  > **username_2**: Right I see - you're trying to `extend` in an include, and that's never going to work... you need to get all this stuff into your `_page` template. It needs: a dynamic `extends` statement, a `content` block, and an `ajaxContent` block. If you want to abstract to an include, do it after the basic version is working.  
  > **username_0**: Let us [continue this discussion in chat](https://chat.stackexchange.com/rooms/110408/discussion-between-a-b-creative-and-username_2).  
  
  ---
  
  