Skip to content

Seamlessly load more content as users scroll, improving engagement and session depth on category archives and single posts.

License

Notifications You must be signed in to change notification settings

xwp/an-infinite-scroll

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

An Infinite Scroll

Seamlessly load more content as users scroll, improving engagement and session depth on category archives and single posts.

Features

  • Category Archives: Unlimited infinite scroll for browsing posts
  • Single Posts: Limited infinite scroll (configurable number of loads) with category-scoped content
  • Performance Optimized: Built-in lazy loading, public caching, and memory management
  • Theme Customizable: Override card templates in your theme for custom styling
  • Admin Controls: Enable/disable infinite scroll independently for categories and posts
  • Accessibility: ARIA attributes and semantic HTML structure
  • Anonymous Requests: No authentication required, fully cacheable responses

How It Works

The plugin uses the WordPress REST API and IntersectionObserver API to automatically load more posts as users scroll down the page. When a user reaches the bottom of the content:

  1. Scroll Detection: IntersectionObserver detects when the user approaches the end of content
  2. API Request: Makes an anonymous, cacheable request to /wp-json/wp/v2/posts with filtered fields
  3. Render Content: Clones a template and populates it with post data (title, image, date, link)
  4. Repeat: Process continues until load limit is reached or no more posts are available

Category Archives

  • Behavior: Unlimited infinite scroll
  • Posts Per Load: Configurable number of posts
  • Category Filter: Only shows posts from the current category

Single Posts

  • Behavior: Limited to a configurable number of automatic loads
  • Category Filter: Shows posts from the same category as the current post
  • After Limit: Displays a "More {Category}" button linking to a configurable page of the category archive
  • Current Post: Automatically hidden from the infinite scroll results

This results in:

  • Improved Engagement: Users discover more content without clicking pagination
  • Better Session Depth: Increased pages per session and time on site
  • Reduced Bounce Rate: Keep users engaged with related content
  • Performance: Efficient loading with field filtering and public caching

Installation

Using Composer

To install the plugin via Composer, follow these steps:

  1. Add the Repository:

    • Open your project's composer.json file.

    • Add the following under the repositories section:

      "repositories": [
          {
              "type": "vcs",
              "url": "https://github.com/xwp/an-infinite-scroll"
          }
      ]
  2. Require the Plugin:

    • Run the following command in your terminal:

      composer require xwp/an-infinite-scroll
  3. Activate the Plugin:

    • Once installed, activate the plugin through the 'Plugins' menu in WordPress.

Manual Installation

  1. Download the plugin files
  2. Upload to /wp-content/plugins/an-infinite-scroll/
  3. Activate through the WordPress admin

Usage

The plugin works automatically once activated and configured. By default, both category archives and single posts have infinite scroll enabled.

Configuring Infinite Scroll

  1. Go to Settings → Infinite Scroll in the WordPress admin
  2. Configure your preferences:
    • Enable on Category Archives: Unlimited scrolling through category posts (enabled by default)
    • Enable on Single Posts: Limited scrolling through same-category posts (enabled by default)
  3. Click Save Changes

Default Behavior

Category Archives:

[X posts] → scroll → [X more posts] → scroll → [X more posts] → ...

(Loads 12 posts per scroll by default, configurable)

Single Posts:

[X posts] → scroll → [X more] → scroll → [X more] → ... → [after Y loads]
→ "More {Category Name}" button linking to /page/Z/

(All values are configurable via admin settings)

Theme Customization

You can override the default card template by creating a custom template in your theme:

  1. Copy templates/card-template.php from the plugin directory
  2. Create a directory in your theme: an-infinite-scroll/
  3. Save your customized version as an-infinite-scroll/card-template.php

The plugin will automatically use your theme's version if it exists. Your custom template should maintain the same class structure for JavaScript functionality:

<template id="an-card-template">
    <article class="an-card">
        <a href="#" class="an-card-link">
            <img src="" alt="" class="an-card-image" loading="lazy" />
            <h2 class="an-card-title"></h2>
            <time class="an-card-date" datetime=""></time>
        </a>
    </article>
</template>

Technical Details

Performance Optimizations

  • Field Filtering: Only requests id, link, title, date, and featured_image_url from the REST API
  • Public Caching: Sets Cache-Control: public, s-maxage={duration}, stale-while-revalidate=30 headers where duration is configurable via admin settings (default: 900 seconds / 15 minutes)
  • Image Optimization: Automatically appends ?w=700 parameter to featured images, loads full-size images on sites without Photon
  • Lazy Loading: Uses native loading="lazy" attribute on images
  • CLS Prevention: Pre-allocated min-height for grid to prevent layout shift
  • Memory Management: Uses content-visibility: auto with contain-intrinsic-size for performance
  • Deferred Loading: Scripts load with defer attribute for non-blocking page load

API Configuration

REST API Endpoint:

GET /wp-json/wp/v2/posts?per_page=12&page=2&_fields=id,link,title,date,featured_image_url&categories=42

Response Headers:

Cache-Control: public, s-maxage={configurable}, stale-while-revalidate=30

The s-maxage value is configurable via the admin settings (default: 900 seconds).

Detection Method:
The plugin detects infinite scroll requests by checking for the presence of the featured_image_url field in the _fields parameter. This triggers the custom caching headers.

Authentication:
Anonymous requests only (credentials: 'omit'). No authentication required for improved caching.

Grid Layout

  • Desktop (≥769px): 3 columns
  • Mobile (<769px): 1 column
  • Gap: configurable via CSS variables between cards (eg. :root:root {--an-infinite-scroll-grid-gap: 1rem;})
  • Card Aspect Ratio: 16:9 for images, images are added as background covers.

Browser Compatibility

The IntersectionObserver API is supported by modern browsers.

Graceful Degradation:
For browsers without IntersectionObserver support, the plugin automatically displays the "More {Category}" button (on single posts) without infinite scrolling functionality.

Admin Configuration

Settings Page

Navigate to Settings → Infinite Scroll to configure all options:

Enable on Category Archives

  • Enables unlimited infinite scroll on category archive pages
  • Only shows posts from the current category
  • Default: Enabled

Enable on Single Posts

  • Enables limited infinite scroll on single post pages
  • Shows posts from the same category as the current post
  • Hides the current post from results
  • Displays "More {Category}" button after reaching the maximum number of loads
  • Default: Enabled

When this option is enabled, the following settings become available:

Posts Per Page (Single)

  • Number of posts to load with each scroll
  • Range: 1-50
  • Default: 12
  • Applies to single posts.
  • Category infinite scroll per page respects the site's global per page configuration such that pagination is matched.

Maximum Loads (Single Posts)

  • Maximum number of times to automatically load posts on single post pages
  • After reaching this limit, the "More" button is displayed
  • Range: 1-20
  • Default: 5

"More" Button Page Number

  • Category archive page number to link to when the "More" button appears
  • For example, setting this to "3" links to /category-name/page/3/
  • Range: 1-100
  • Default: 3

Cache Duration

  • How long infinite scroll API responses should be cached
  • Shorter durations show fresher content, longer durations improve performance
  • Options: 1 minute, 5 minutes, 15 minutes, 30 minutes, 1 hour, 4 hours, 12 hours, 24 hours
  • Default: 15 minutes (900 seconds)

Technical Settings

The following values are hardcoded in the JavaScript:

  • Loader Trigger Distance: 800px before end of content

Known Limitations

  1. Paginated Archives: Infinite scroll is disabled on paginated URLs (e.g., /category/news/page/2/)
  2. Multiple Categories: When a post has multiple categories, only the first category is used for filtering
  3. Error Handling: API request errors fail silently (logged to console)
  4. Single Category Only: On single posts, only shows related posts from the first assigned category

Plugin Structure

an-infinite-scroll/
├── an-infinite-scroll.php          # Main plugin file
├── includes/
│   ├── class-infinite-scroll.php   # Core functionality
│   ├── class-rest-api.php          # REST API customizations
│   └── class-settings.php          # Admin settings page
├── templates/
│   └── card-template.php           # Default card template
├── assets/
│   ├── js/
│   │   └── infinite-scroll.js      # Frontend JavaScript
│   └── css/
│       └── infinite-scroll.css     # Frontend styles
└── README.md

Requirements

  • WordPress: Version 5.0 or higher
  • PHP: Version 8.1 or higher
  • Browser: IntersectionObserver support (95%+ browsers) or graceful fallback

Hooks & Filters

Currently, the plugin doesn't provide custom hooks or filters. All customization is done through:

  • Theme template overrides
  • Admin settings page
  • Direct code modification (for advanced users)

Support

For issues, feature requests, or contributions:

License

This plugin is licensed under the GPLv3 or later.

About

Seamlessly load more content as users scroll, improving engagement and session depth on category archives and single posts.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published