Adding Page Transitions to WordPress

Recently I have worked on 2 projects where I have used Wordpress with smoothstate.js, let’s find out how smoothstate.js can add page transitions to your website!

What is smoothstate.js?

According to Miguel Ángel Pérez (author of smoothstate.js):

“We’ve accepted the jankiness of page loads as a quirk of the web even though there is no technical reason for it. smoothState.js lets you add transitions to eliminate the hard cuts and white flashes of page loads that deface the beauty of the user experience.”

smoothstate.js is a Javascript library that allows you to load page content via AJAX, giving us more control over page transitions. It utilises HTML5’s pushState API which is widely supported by modern browsers. On older browsers, smoothstate.js is automatically disabled in the background and fallback to regular page load.

Without smoothstate

Without smoothstate.js, note that there are no loading screen or exit animation

With smoothstate

smoothstate.js allows you to add exit animation and loading screen for a seamless transition.

How I Use smoothstate.js with WordPress

First include jQuery, then include smoothstate.js (you can download from: https://github.com/miguel-perez/smoothState.js) into your site like so:

<script src="/your/path/to/jquery.js"></script>
<script src="/your/path/to/jquery.smoothState.js"></script>

Here is a basic example on how to setup all your pages. The idea is to have a container with the same id on every page, initialise smoothstate.js on this container and everything inside the container will be replaced by data from AJAX call. Every URL on your site should return a full layout – not just an HTML fragment.

You can do something like this in your theme’s layout template:

<body>
  <div class="loading-overlay">
  </div>
  <div id="main" class="m-scene">
    <div class="<?php echo $this['config']->get('body_classes'); ?>">
      <div class="scene_element scene_element--fadein">
        <!-- contents... -->
      </div>
    </div>
  </div>
</body>

Together with the following CSS, anything inside .scene_element--fadein will fade in once the page is loaded. You can also create your own keyframes or use other animation frameworks such as Animate.css.

/*
 * CSS Animations
 * Don't forget to add vendor prefixes!
 * From: http://smoothstate.com/typical-implementation.html
 */
.m-scene .scene_element {
  animation-duration: 0.25s;
  transition-timing-function: ease-in;
  animation-fill-mode: both;
}

.m-scene .scene_element--fadein {
  animation-name: fadeIn;
}

.m-scene.is-exiting .scene_element {
  animation-direction: alternate-reverse;
}

/*
 * Keyframes
 */
@keyframes fadeIn {
  0% { opacity: 0; }
  100% { opacity: 1; }
}

Then in your own script file, you can initialise smoothstate with the following:

// From: http://smoothstate.com/typical-implementation.html
;(function($) {
  'use strict';
  var $body = $('html, body'),
      content = $('#main').smoothState({
        // Runs when a link has been activated
        onStart: {
          duration: 250, // Duration of our animation
          render: function (url, $container) {
            // toggleAnimationClass() is a public method
            // for restarting css animations with a class
            content.toggleAnimationClass('is-exiting');
            // Scroll user to the top, this is very important, transition may not work without this
            $body.animate({
              scrollTop: 0
            });
          }
        }
      }).data('smoothState');
      //.data('smoothState') makes public methods available
})(jQuery);

The above code essentially initialises smoothstate.js on your #main div. When you click on any internal links, content inside #main will be replaced by #main on the next page. Duration is telling the browser to wait until animation finish (250ms) before fetching the content on next page.

Notable options (full documentation):

  • debug: if you are experiencing problems, you can turn debug on by setting it to true. Then smoothstate will log useful information to console.
  • blacklist: you don’t want to add transition to every link, for example you don’t want to use smoothstate for WordPress admin bar, dropdown links or images. You can easily blacklist them using the jQuery selector:
    blacklist: ".no-smoothstate, .post-edit-link,  a[href*='.jpg'], a[href*='.png'], a[href*='.jpeg'], a[href*='.pdf']"

Add loading screen between transitions

Fetching data often takes much longer than the animation. Having user staring at a blank screen will lead to panics and frustrations. Adding a loading overlay lets users know that the website is still loading. It also acts as a cover for any screen flickering or abnormal behaviour caused by the animations.

The following is a very simple example that fades in an overlay during onStart function and then fades out the overlay inside onAfter function.

;(function($) {
  'use strict';
  var $body = $('html, body'),
      content = $('#main').smoothState({
        // Runs when a link has been activated
        onStart: {
          duration: 250, // Duration of our animation
          render: function (url, $container) {
            // toggleAnimationClass() is a public method
            // for restarting css animations with a class
            content.toggleAnimationClass('is-exiting');
            // loading overlay starts fading in after 250ms
            $('.loading-overlay').fadeOut();
            // Scroll user to the top, this is very important, transition may not work without this
            $body.animate({
              scrollTop: 0
            });
          }
        },
        // runs when the new content has been injected into the page and all animations are complete
        onAfter: function($container, $newContent) {
            // once content has loaded, loading overlay can fade out
            $('.loading-overlay').fadeOut();
        }
      }).data('smoothState');
      //.data('smoothState') makes public methods available
})(jQuery);

Potential issues

If you have plugins that initialise on page load (e.g. inside $(document).ready()), you will have to initialise again in onAfter. That is because smoothstate.js is not reloading the page, it is just replacing content within the page and therefore anything inside $(document).ready() will not run again.

Parting words

And there you have it, this is just a very simple tutorial on how to implement smoothstate.js into your WordPress site. There are so many more possibilities, you just have to be creative!

Be sure to checkout the work we did using smoothstate.js with WordPress!