Implementing page transitions without AJAX

One way to bring a rather dull page into life is to add some page transitions. This way when a visitor follows some links around, pages won't switch at an instant, but smoothly escorted from one to another.

There are several JS libraries1 out there that provide a way to implement such features. Most use AJAX, some PJAX2, and they do include numerous UX enhancements that this implementation never aims or claims to solve. This is just a simple progressive enhancement in the order of several hundred bytes with no external JS or CSS to include. Use them if you need something more. They are better but require a bit more elaborate setup, which may prove difficult to maintain later on.

Simplicity is the ultimate sophistication. Leonardo da Vinci

How does it work?

DOM tree is built as HTML is parsed from top to bottom. This means you cannot access to a DOM nodes before it is parsed. One way to overcome this is to listen to DOMContentLoaded event that JQuery improves with cross-browser normalization with with $.ready() method. But we'll use neither. The reason is that we shouldn't wait for the whole DOM is built, because after DOMContentLoaded event page content is already rendered and displayed to user. Instead, we'll put our script just after a container elements opening tag, which is executed right after the element is added to DOM tree. Then immediately modify it with some classes, and remove it afterwards.

Animating page load

To get the effect, following example should suffice. Right after container element, we place the script, make the container transparent, then remove the effect with a timeout.

<div id="container">
    <!-- place the script right after the container -->
    <script>
        (function () {
            var container = document.getElementById('container');
            // here we set the initial state before animation
            // change some styles, add some classes, go wild!
            container.style.opacity = 0;

            setTimeout(function () {
                // then restore it to working state
                container.style.opacity = 1;
            }, 200); // after 0.2 seconds
        })();
    </script>

    <!-- rest of the content -->
</div>

Remember to add some transitions in your CSS as well, otherwise you won't see a difference. You should load your CSS, or put it inside a <style> tag before the container, so it will be styled correctly. Or just use inline styles, <div id="container" style="transition: 0.2s ease-out;"> if you really want to keep it all together.

#container {
    transition: opacity 0.5s ease-out;
}

This snippet is enough get fade in animation during a page load. Yet, this can be extended by listening to an event instead of a timeout, for instance you'd probably want the images to load before showing it to user. Or use some classes with more intricate animations instead of simply fading in. Codrops is a rich source of high qualityinspiration in this regard.

Animating page change

Load animation is just one part. What about when user clicks away from the page? How do we hide the content?

Before a page change, beforeunload event is fired. We can listen to this event, and make our changes. You can hide the content with some animation, and choose to show a spinner to fill the white void. One thing to note is that since we don't preload the content, after user clicks away from the page, and before the next page is loaded, page will flash for a brief moment depending on how fast server responds, so your spinner may experience some flicker. Here's a sample implementation:

window.addEventListener('beforeunload', function () {
    // here make the page as similar
    // to the initial state as possible
    container.style.opacity = 0;
});

This is all there is to it. We could've used a scale-fade animation that looks really slick, but that's left as an exercise to the reader. This website uses a version of this code, and it's not much more involved than this, but it does the job simply and beautifully, it's a "great if it works, no problem if it doesn't" kind of enhancement with no reason to cause user frustration.


  1. Examples include Barba.js, and smoothState.js⚓︎

  2. PJAX is AJAX with pushState() implementation, used for changing user history when pages are loaded with AJAX. ⚓︎