- Overview
- Documents
Animated Page Transition replaces the refresh of a web page with an animation, that takes place while the new page content is loaded using Ajax. We used the pushState method to manipulate the browser history.

Source: codyhouse.co
1. HTML
The HTML structure is composed of a <main> element, wrapping the page content, a div.cd-cover-layer which is used to create the layer covering the content during the page transition, and a div.cd-loading-bar to create the loading bar animation.
<main> <div class="cd-index cd-main-content"> <div> <h1>Page Transition</h1> <!-- your content here --> </div> </div> </main> <div class="cd-cover-layer"></div> <!-- this is the cover layer --> <div class="cd-loading-bar"></div> <!-- this is the loading bar -->
2. CSS
We used the body::before and body::after pseudo-elements to create the 2 blocks that cover the page content during the page transition: these elements are in fixed position, with height equal to 50vh and width equal to 100% of the viewport. By default, they are hidden outside the viewport using the CSS transform property (translateY(-100%)/translateY(100%)). When the user triggers a page transition, these elements are moved back into the viewport (using the .page-is-changing class added to the <body> element).
Here is a quick animation that shows the starting position of the body::before, body::after and the div.cd-loading-bar elements (gif created in After Effects):
body::after, body::before {
/* these are the 2 half blocks which cover the content once the animation is triggered */
height: 50vh;
width: 100%;
position: fixed;
left: 0;
}
body::before {
top: 0;
transform: translateY(-100%);
}
body::after {
bottom: 0;
transform: translateY(100%);
}
body.page-is-changing::after, body.page-is-changing::before {
transform: translateY(0);
}
The fade-out effect of the page content during the page transition is achieved animating the opacity of the div.cd-cover-layer. It covers the entire .cd-main-content element, has the same background-color, and its opacity is animated from 0 to 1 when the .page-is-changing class is assigned to the <body>.
The progress bar animation is created using the .cd-loading-bar::before pseudo-element: by default, it is scaled down (scaleX(0) and transform-origin: left center), while it is scaled back up when the page transition is triggered (scaleX(1)).
.cd-loading-bar {
/* this is the loading bar - visible while switching from one page to the following one */
position: fixed;
height: 2px;
width: 90%;
}
.cd-loading-bar::before {
/* this is the progress bar inside the loading bar */
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 100%;
transform: scaleX(0);
transform-origin: left center;
}
.page-is-changing .cd-loading-bar::before {
transform: scaleX(1);
}
Smooth animations are achieved using CSS Transitions. We have been using a different transition-delay value for each animated element in order to perform the different animations in the right order.
3. EVENTS HANDLING
We have been using the data-type="page-transition" to target the links triggering the action. When a click event is detected, the changePage() function is executed:
$('main').on('click', '[data-type="page-transition"]', function(event){
event.preventDefault();
//detect which page has been selected
var newPage = $(this).attr('href');
//if the page is not animating - trigger animation
if( !isAnimating ) changePage(newPage, true);
});
This function triggers the page animation and loads the new content (loadNewContent() function):
function changePage(url, bool) {
isAnimating = true;
// trigger page animation
$('body').addClass('page-is-changing');
//...
loadNewContent(url, bool);
//...
}
When the new content is loaded, it replaces the old content inside the <main> element, the .page-is-changing class is removed from the body (to reverse the page animation) and the new loaded page is added to the window.history (using the pushState() method).
function loadNewContent(url, bool) {
var newSectionName = 'cd-'+url.replace('.html', ''),
section = $('<div class="cd-main-content '+newSectionName+'"></div>');
section.load(url+' .cd-main-content > *', function(event){
// load new content and replace <main> content with the new one
$('main').html(section);
//...
$('body').removeClass('page-is-changing');
//...
if(url != window.location){
//add the new page to the window.history
window.history.pushState({path: url},'',url);
}
});
}
In order to trigger the same page animation when user clicks the browser back button, we listen for the popstate event, and execute the changePage() function when it is fired:
$(window).on('popstate', function() {
var newPageArray = location.pathname.split('/'),
//this is the url of the page to be loaded
newPage = newPageArray[newPageArray.length - 1];
if( !isAnimating ) changePage(newPage);
});
JS Tutorial
