Animate Any WordPress Block when Scrolling

Learn how to animate any WordPress block when it scrolls into view. There’s very little code and you can add it to any WordPress site without installing a new plugin. We’ll use the off-the-shelf AOS library to do the main work for us, and we’ll add a bit of code to functions.php to make it work. It’s a nice way of adding a bit of bling to a site’s front page 😎 🥇

How It Will Work

We’re going to create a simple shortcode that lets us wrap any WordPress Gutenberg Block in a <div> element. We’ll give this element some specific properties, and the AOS library will do the rest for us.

In the Block Editor…

…In the Front End

motion

So… all we need to do is…

  • Create a shortcode called “aos_anim” (in PHP) and pass some AOS parameters into it, like anim=”…” and duration=”…”
    • This shortcode will take a closing shortcode so it can be wrapped around one or more blocks.
  • Enqueue the AOS assets.
  • Create a few of lines JavaScript to link it together in the browser.

Before We Start

First off, make sure you’re using a custom child theme so you can edit functions.php. In your custom child theme’s main folder, create a new sub-folder called “aos-anim“. Then grab the latest stable version of AOS from GitHub. At the time of writing, the stable version was 2.3.4…

Download the zip file, extract it, and go into the “dist” (distribution) folder. You should see two files in there, called aos.css and aos.js. Copy these into the aos-anim folder in your custom child theme.

In this “aos-anim” directory, create an empty text file called aos-anim-frontend.js. We’ll put a bit of JavaScript code in there later. For now, the file just needs to exist.

In the main directory of your custom child theme, create a new PHP file called aos-anim.php. Again, just leave it empty for now, but make sure you save it.

Next, open functions.php in your custom child theme’s main folder and add the following couple of lines to it: This will pull our new code into the theme so we can register our shortcode.

/**
 * WP Tutorials AOS Anim.
 */
require_once dirname(__FILE__) . '/aos-anim.php';

That’s the scaffold in-place. Reload your site and make sure you’ve not broken anything.

Let’s Write the Actual Code

The main lump of code is pretty straightforward. Open aos-anim.php and paste the following into it, then look through the comments to see what it’s doing.

<?php

/*
 * WP Tutorials :: Animate on Show.
 *
 * https://wp-tutorials.tech/refine-wordpress/animate-any-wordpress-block-on-scroll/
 *
 * Thanks to: AOS: http://michalsnik.github.io/aos/
 */

// Block direct access.
defined('WPINC') || die();

const WPT_AOS_VERSION = '2.3.4';

/**
 * Test to see if some content is either just a shortcode by itself, or just a
 * shortcode wrapped in paragraph tags.
 */
function wpt_is_a_shortcode(string $content) {
    $is_a_shortcode = false;

    $strip_tags = array('/^<\/p>/i', '/<p>$/i', '/^<p>/i', '/<\/p>$/i');
    $test_content = preg_replace($strip_tags, '', trim($content));
    if (strlen($test_content < 3)) {
        // Not a shortcode
    } elseif (substr_count($test_content, '[') != 1) {
        // Not a shortcode
    } elseif (substr_count($test_content, '[') != 1) {
        // Not a shortcode
    } elseif (substr($test_content, 0, 1) != '[') {
        // Not a shortcode
    } elseif (substr($test_content, -1) != ']') {
        // Not a shortcode
    } else {
        $is_a_shortcode = true;
    }

    return $is_a_shortcode;
}

/**
 * Add the animate-on-show assets to the frontend, with our small  piece of
 * JavaScript to activate it after the page has loaded.
 */
function wpt_require_aos() {
    global $wpt_has_aos_been_required;

    if (!is_admin() && is_null($wpt_has_aos_been_required)) {
        $base_url = get_stylesheet_directory_uri() . '/' . pathinfo(__FILE__, PATHINFO_FILENAME) . '/';
        $version = wp_get_theme()->get('Version');

        wp_enqueue_script('aos', $base_url . 'aos.js', null, WPT_AOS_VERSION, true);
        wp_enqueue_style('aos', $base_url . 'aos.css', null, WPT_AOS_VERSION);

        wp_enqueue_script('wpt-aos', $base_url . 'aos-anim-frontend.js', array('aos'), $version, true);

        $wpt_has_aos_been_required = true;
    }
}

function do_shortcode_wpt_aos_anim($atts = array(), $content = null) {
    $html = '';

    if (is_admin()) {
        // Don't do anything.
    } elseif (wp_doing_ajax()) {
        // Don't do anything.
    } else {
        // Enqueue the assets.
        wpt_require_aos();

        // Options listed here:
        // https://github.com/michalsnik/aos/tree/v2#-advanced-settings
        // The "class" option is own own - not one of AOS' options.
        // The "anim" option is special, and maps to data-aos=".."
        $args = shortcode_atts(
            array(
                'anim' => 'fade-up',
                'offset' => 120,
                'delay' => 0,
                'duration' => 400,
                'easing' => 'ease',
                'anchor' => '',
                'anchor-placement' => 'top-bottom',
                'once' => false,
                'class' => '',
            ),
            $atts
        );

        if (empty($args['anim'])) {
            $html .= $content;
        } else {
            // Open our <div>
            $html .= sprintf('<div data-aos="%s"', esc_attr($args['anim']));

            // Loop through the $args and add them as data-aos-... properties - apart from
            // the "anim" $key, because we've already added that one as data-aos="..."
            foreach ($args as $key => $value) {
                if (($key != 'anim') && !empty($value)) {
                    $html .= sprintf(' data-aos-%s="%s"', $key, esc_attr($value));
                }
            }

            // If we've been passed something in class="..." then add it now.
            if (!empty($args['class'])) {
                $html .= sprintf(' class="%s"', esc_attr($args['class']));
            }

            $html .= '>';

            // Sometimes do_shortcode returns a string that starts with a
            // closing paragraphc tag and ends with an opening paragraph tag.
            // This is invalid HTML, so we should detect this and fix it.
            $patterns = array('/^<\/p>/i', '/<p>$/i');
            $content = preg_replace($patterns, '', $content);

            // If the content is just a shortcode by itself then WordPress will
            // wrap it in paragraph tags. Strip these out to give us the raw
            // content from the shortcode.
            if (wpt_is_a_shortcode($content)) {
                $inner_html = trim(do_shortcode($content));
                $patterns = array('/^<p>/i', '/<\/p>$/i');
                $inner_html = preg_replace($patterns, '', $inner_html);
            } else {
                $inner_html = do_shortcode($content);
            }

            // Add the inner HTML to the output.
            $html .= $inner_html;

            // Close our div... Job done.
            $html .= '</div>';
        }

    }

    return $html;
}
add_shortcode('aos_anim', 'do_shortcode_wpt_aos_anim');

That’s all there is to the PHP. Now, we just need to tie things together in the frontend with a bit of JavaScript. The AOS documentation says all we need to do is call AOS.init(). We’ll use a standard jQuery snippet to do this once the window/document has fully loaded. We could easily do it without using jQuery, but I’ve used it here to keep the code consistent with the other tutorials on this site.

Open aos-anim/aos-anim-frontend.js, paste the following into it, and save the file.

(function($) {
    'use strict';

    $(window).on('load', function() {
        if (typeof AOS != 'undefined') {
            // Uncomment this to verify that the JS is loading correctly in the browser's JS Console.
            // console.log('Initialise AOS');

            AOS.init();
        }
    });
})(jQuery);

Finish & Test

Example opening shortcode.

Make sure everything is saved, then create/edit some content on your site. The shortcode will work without any parameters at all, or you can pass things like anim="zoom-in-left". Just choose from any of the list of available AOS animations.

importantDon’t forget the closing shortcode when you’re wrapping your blocks.

Going Further

You’ll see that we only enqueue the AOS assets the first time our shortcode gets used on a page. This is to keep your site clean… reducing unused CSS/JS on pages that don’t have animations. However, you can call wpt_require_aos() from a wp_enqueue_scripts action handler so you can use animations all over the place.

After you’ve called wpt_require_aos(), you can also start loading things like data-aos="flip-left" into your post archive pages too. It looks pretty cool when mixed with a masonry layout, like on our Ipsum text generators site.

Happy animating! 😎 👍

2 thoughts on “Animate Any WordPress Block when Scrolling”

  1. I can’t add “require_once dirname(__FILE__) . ‘/aos-anim.php’;” to functions.php.
    The system display as following:

    Your PHP code changes were rolled back due to an error on line 0 of file Unknown. Please fix and try saving again.

    1. The problem might not be with the require_once code. There might be a problem in “aos-anim.php” itself. I’ve just retested it here and it works fine.

      Maybe there is something different about your server/configuration? What version of WordPress and PHP are you using? I just tested it on WordPress 5.8.2 and PHP 8.0.13. Also, can you check your site’s error log? There is probably some useful information in there.

Leave a Comment

Your email address will not be published. Required fields are marked *