I first came across pjax (pushState + ajax) when I was working on a Rails 4 project which has Turbolinks. Turbolinks isn’t pjax per se. It’s similar and based on the same philosophy.
How pjax works
Instead of re-rendering a full page on every page request, pjax fetches only a fragment of the target page and uses that to replace its counterpart in the current DOM, thereby preserving the surrounding layout, scripts and style. Because the browser doesn’t have to compute the scripts and styles, rendering time is next to nothing. New pages can also be strategically prefetched to make page changes as fast as DOM replacement. The address bar is also updated instantaneously with HTML5 History API.
Imagine a train which upon leaving the current station, instantly vanishes and reappears at the next station, jumping space and time. It would be an unsettling mode of transportation because you wouldn’t have a sense of how you got there. pjax feels like teleportation. The abrupt change makes one feel disoriented. Transitions are necessary to make the change smoother.
I’m using the jquery-pjax plugin on this site. The plugin provides some handy APIs for we can make use of to add transitions between page loads.
Click around this site to see its cross fade transition.
This is the function for loading content via pjax. I used the
fragment option to tell jquery-pjax to grab the
#main element from the target DOM. If you are serving dynamic i.e. PHP or Ruby pages and can output layout-less content then you can don’t need to use
I then handle clicks on links I want to be pjaxified. It’s also important to ensure the browser supports pjax with
$.support.pjax. Otherwise the links will not be handled and will not be pjaxified.
At this point, pjax works. But it feels like teleportation. We need to add transitions and this is how they will work.
- Clone the element to be replaced.
- Stack it on top of the original.
- Replace the original (handled by plugin)
- Fade out the clone.
- Remove the clone.
#main and then stack
#clone above and prevent scrolling.
pjax:end, fade out
pjax:end you can easily create other kinds of transitions.