Page Transitions in WordPress with SmoothState

SmoothState.js is a javascript library that adds transitions between pages on your site using AJAX. I use it on this site to help create a more seamless experience when going through pages. Aside from transitions, it can also be used to increase the speed of your site slightly.


jQuery is required for SmoothState. If you already have a theme, its more than likely the theme already has jQuery registered. If you’re building your own, and you haven’t added it yet, add this to your functions.php:


Once you’ve added jQuery, ensure any links to your internal pages are full URL’s, and not just an ID or HTML fragment. If you have a nav that scrolls you down the page, I’ll show you how to excludes those from the SmoothState so that they continue to work.

By default, SmoothState won’t add transitions, so it will jump. I’ve included Animate.css in my theme and use.

Getting Started

Download jquery.smoothstate.js and place it in your theme with other JS files. You can add it to an existing js file or register and enqueue it separately:

function load_my_script(){
    wp_register_script('smoothstate', get_template_directory_uri() . '/assets/js/plugins/particles.js', array() , null,  true);
add_action('wp_enqueue_scripts', 'load_my_script');

Next we’ll need to create a container basically wraps around everything that will be injected. I open this div right after the <body> and close it right before </body>. I do call the footer in this container. In this instance, I gave the container an ID of SmoothBody. I also added a class of m-scene, which we will add CSS3 animation properties too.

<?php get_template_part('templates/head'); ?>
<body <?php body_class(); ?>>
    <div id="smoothBody" class="m-scene">
     <!-- the rest of the page and sidebar -->
        <?php get_template_part('templates/footer'); ?>

Do note, that if you rely on classes on the body to style, they will not change when you go to a new page unless repeat put them inside the container.

Configuring the SmoothState

Now that the container is in place, we’ll tie it in to our SmoothState and begin. Either in the javascript file you added earlier, or a new one, all you need to do is:

// Contents of functions.js
;(function ($) {

At this point, the content should reloaded through AJAX in the container instantly. If its not working, inspect the console for errors and check to make sure you have jQuery, SmoothState.js, then the function we declared, in that order. If you’re still stumped, you can always comment below for help or tweet at the author Miguel Pérez.

Here’s the SmoothState function that I have implemented on my site. I’ve commented it as well to explain it.

		  'use strict';
		  var options = {
		    prefetch: true,
		    blacklist: '.no-smoothState', //links with this class are ignored, like my open menu button
		    scroll: true,
		    cacheLength: 2,
		    onStart: {
		      duration: 500, // Duration of our animation, if animations are longer than this, it causes problems
		      render: function ($container) {

		        // Add your CSS animation reversing class
		        // Restart your animation. 
		        //If you looked at the authors demo, it uses .toggleAnimationClass(), which is outdated now
		        //The Smoothstate demo on the authors site is outdated, but his Github is up to date and uses this method now.
		    onReady: {
		      duration: 0,
		      render: function ($container, $newContent) {
		        // Remove your CSS animation reversing class
		        // Inject the new content
		  smoothState = $('#smoothBody').smoothState(options).data('smoothState');

Adding Animations

Lastly, to add the animations in, i’ll be utilizing CSS3 animations, particularly animate.css. If you haven’t already, add that into your sites CSS. Earlier, we added the m-scene class to the container div, because using the ID in css is slower than a class.  Here’s the CSS used to add in animations:

 * CSS Animations
 * Don't forget to add vendor prefixes!
.m-scene .scene_element {
  -webkit-animation-duration: 0.25s;
  animation-duration: 0.25s;
  -webkit-transition-timing-function: ease-in;
  transition-timing-function: ease-in;
/* this means that before the animation runs, the element will have the starting css rules, then keep the end rules */
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;  }

.m-scene .scene_element--fadeIn {
  -webkit-animation-name: fadeIn;
  animation-name: fadeIn;
} .scene_element {
  -webkit-animation-direction: alternate-reverse;
  animation-direction: alternate-reverse;

In the example above, each element that animates should have the scene-element class, which controls the duration, fill mode, timing mode (ease-in). A second class, in this case scene-element–fadeIn, tells us which animation to run. With that in place it, your site should now be transitioning between pages. Let me know if you ran into trouble or need help!