May 20, 2015 | 111 Feedbacks

Animated Page Transition

A CSS powered animation, that replaces the refresh of the page while the content is updated using Ajax.
Browser support
  • ie
  • Chrome
  • Firefox
  • Safari
  • Opera

We’ve been playing around the idea of replacing 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.

Inspiration came from this beautiful website:

Creating the structure

The HTML structure is composed of a <main> element, wrapping the page content, a which is used to create the layer covering the content during the page transition, and a to create the loading bar animation.

Adding style

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 elements (gif created in After Effects):

page transition

The fade-out effect of the page content during the page transition is achieved animating the opacity of the 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)).

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.

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:

This function triggers the page animation and loads the new content (loadNewContent() function):

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).

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:

You can read more about the popstate event and how browsers handle it here.

Note: we implemented a basic load() function to upload new content, but you may want to replace it with, for example, a $.ajax call in order to handle errors, etc.


Oct 2, 2015
  • Bug fixed - animation wrongly reloaded with anchor tags linking to the same page
May 20, 2015
  • Resource released by CodyHouse

Claudia Romano

Web developer, fan of The Big Bang Theory and good food. Co-founder of CodyHouse and Nucleo. You can follow her on Twitter.

  • amit

    awesome :)

  • BioButterfly

    This is great. As always! ;)

  • i.v.schagen

    Awesome!! Such nice work!

  • Chrill115

    Great solution, but it’s not fine for SEO ?

    • tony

      What is wrong with SEO here? It works as intended and also works in IE9, the animation does not work in IE9 but the content loads.

      This animation is useful for single page applications, which can also be tuned for better SEO.

      • Chrill115

        head tags ? (title, description)

        • tony

          This is just a demo, in the real world you would have normal title and description.

          So I don’t see how this affects SEO?

    • Pau

      No efects SEO cause the script change the URL and google identify a link in page and can analize the, in this case, about.html. ;)

      • Chrill115

        Yes, it’s alright ! sorry for this error ^^

  • Youssef Seghir

    I just love CodyHouse ! Thanks for sharing :) !

  • Patrick Schubert

    Does anybody know if this AJAX load technique works on a more sophisticated page? I tried implementing something like this on a wordpress page which also does a lot of JS stuff on document.ready and trying to just push the new content via ajax obviously broke the whole page! :-/
    Anybody any ideas on this?! :-)

    • Kirill

      just use permalink : ‘information’, ‘posts_per_page’ => -1 );
      $loop = new WP_Query( $args ); ?>
      have_posts() ) : $loop->the_post(); ?>

      <a class="cd-btn" href="” data-type=”page-transition”>

  • Mehedi Hasan

    Great Tutorial :)

  • superhuit

    Great article guys, as always!
    It’s a blast to see that something we’ve done inspires other people, too :-)

    • Claudia Romano

      Thank you guys! and love your jardins-poudriere project :)

    • Antoine Horiot

      I’m getting a lot of inspiration from your work as well !

  • kulderzipke

    the demo is working in chrome but the downloadable version is not working in chrome?

    • Santiago Moreno

      Hi, setup a local server or upload it to your hosting if you have one, then it will work on chrome. Don’t know why but that is, something to do with XMLHttpRequest in chrome. Or just develop it in firefox.

  • Kirill

    to Kulderzipke .They forgot this: (function(i,s,o,g,r,a,m){i[‘GoogleAnalyticsObject’]=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,’script’,’//’,’ga’);
    ga(‘create’, ‘UA-48014931-1′, ‘’); ga(‘send’, ‘pageview’);
    jQuery(document).ready(function($){ $(‘.close-carbon-adv’).on(‘click’, function(event){ console.log(”); event.preventDefault(); $(‘#carbonads-container’).hide(); }); });

  • taylan

    I been waiting for this tutorial :) Cool! Thanks so much!

  • Carson Gross

    Awesome work. I’d love to integrate this functionality into intercoolerjs!

    Thanks for the great demo.

    • Mirko

      Would absolutely love to see that!! Intercooler is great for those not wanting to get their hands dirty with JS / AJAX, but it really misses some nice page animations/transitions.

      • Carson Gross

        Hi Mirko,

        I have introduced CSS transitions into intercooler:

        • Mirko

          That is great news. As a matter of fact I went to intercooler website a few days ago looking to see if that maybe happened!

  • Šime Vidas

    There should be a “fast track” for when the next page is displayed from the browser’s cache. Having to wait the full ~2 seconds for the animation to complete makes the app feel “Flashy”. As one smart person wrote a while ago: “Animations should be invisible.”

  • Austin Wulf

    This looks nice but could actually cause your users to perceive the page load as slower. Wouldn’t it be better to just optimize your page load times so that the next page appears to load instantly?

  • Joel

    Sweet! I was looking for a while for this. Thanks for share.

  • Mergim Ujkani

    Awesome! this is just what I needed, I did built something similar Thank you guys.

  • TheVirusKA

    How would I get rid of the border

    • Sebastiano Guerriero

      the border is the padding applied to the element

  • Marius NGADOM

    Very good article !

  • Bazza

    First of all… AWESOME! I’m loving not only your work but this whole site! It’s incredibly inspirational.
    just battling a bit. The page transition code is mixing with other JS
    on my site and I’m just too limited in JS to work out a solution.

    I really want to use this as my other solutions SUCK!! :( Please Please
    help. I’m sure other people are going to have this problem as well

    • Stephen Nixon

      I know very little about JS, but I think it’s likely that your problem is due to “scoping” – your JS variables are somehow mixing globally, rather than just within the proper functions, and thus the conflict. The solution, then, would be to read up on scoping, and how to make a global variable local*.

      *This is my best guess. Good luck!

  • Tim Rowley


  • J O M S

    Tried downloading this… But I have an issue regarding this. When I changed the file extension name from .html to .php it doesn’t work correctly. What seems to be the problem? TIA !

    • Thee

      HTML and PHP are two different languages. If you change an extension, you’d likely have to convert or change your code to the new language in order for things to work.

      Similarly, changing a CSS file to HTML, or JS would still result in pages not working for you, since they are different.

      You could maybe call the HTML page via the PHP?

    • Vimal rishi

      Hi J O M S,
      Check the main.js file. In loadNewContent() around line 44, you’ll find this line,
      var newSection = ‘cd-‘+url.replace(‘.html’, ”);
      Adjust the extension to suit your needs.

      Hope that helps.

  • Toaitrantien

    Awesome post @claudiarrromano:disqus , thanks again for great job!!.

    Hey Claudia, can you please tell me where i can create the gif images as you used on the article?. Like this?

    If there’s a plugin or software, it would be greateeeeee!!.


    • Joel

      (gif created in After Effects)

      • Toaitrantien

        thanks mate

      • Toaitrantien

        any keyword to search, or a build in template so i can base on that to follow?, sorry since im totally noob about this

  • Haobin Liang

    Exactly what I needed! Thanks!

  • MiguelBonifaz123

    Muchas gracias!

  • Antony Disez

    Hi Claudia,
    Your technique seems amazing, thanks for posting it !

    But, do you know why when I download your files, my console says :
    Uncaught SecurityError: Failed to execute ‘pushState’ on ‘History’ ??

    • Claudia Romano

      Hi Antony, are you experiencing this issue on Chrome only? In that case, uploading the files on a local server should solve the problem (give a look at the comment of Santiago Moreno below). Hope this helps!

  • Erblin Derguti

    Guys I have a problem, when I go in next page ( ex. about.html ) the css won’t load. After I refresh the page everything its okay.

    • Claudia Romano

      Hi Erblin, are you referring to a css file not included in the index.html? What we do is to load the content of the new page (what’s inside the .cd-main-content) but not additional style (which are inside the head of the new page). Hope this helps!

      • Erblin Derguti

        Thanks for reply Claudia,

        May you take a look here:

        If you can send me a message in twitter @ErblinDerguti i would provide you the FTP or cPanel ( If you would have time to check it ofc. )

        Thank you.

        • Vimal rishi

          Hi Erblin,

          If you want to load other pages properly you need to update your page, style.css as well as main.js.
          For example if you are using a page called contacts.html, then change this line
          to and this line to .

          Because, in main.js the file name is used to create a section. Similarly in the main.js look for the line ( section.hasClass(‘cd-about’) ) ? $(‘body’).addClass(‘cd-about’) : $(‘body’).removeClass(‘cd-about’); and add another one just below it,
          ( section.hasClass(‘cd-contacts’) ) ? $(‘body’).addClass(‘cd-contacts’) : $(‘body’).removeClass(‘cd-contacts’);

          Now in style.css, search for all the classes that have .cd-about copy and paste them at the bottom and replace cd-about with cd-contacts. (Mind you this is only for the newly copy pasted one) so, you will have two sets of classes, one for about and one for contacts.

          And you are done. Repeat this process for all the pages you add. remember the section name is your-page-name minus the extension, which is html.


          • peter nunn

            Thanks so much Vimal. This was something that i was stuggling with and you solution worked perfectly.

  • Valerio

    Can I use this library with AngularJS? Thank you

  • Cristiano Menger

    Hi! Great post! I don’t know too much about code but i tried to include more pages and it didn’t work :/ There is a “←” in the go back link and if all the new pages has it the button go back doesn’t work… thanks

    • Erblin Derguti

      Hi, have you hosted somewhere ? Maybe we can take a look into it. ?

  • form9hide

    How will this behave in older IE versions?

  • Chris Talk A Lot

    Very useful and loving it. How do I add a second page? The second page seems to break down and only works after refresh.

    • Erblin Derguti

      Its happening to me too.

  • Nefertiti Kimagawa

    I’m working in chrome and when i got to transition tot he next page it won’t just stays on index and won’t go to about. the demo version works but not what i downloaded I have it downloaded to my local and it’s transitioning but it’s like it’s stuck on index and the about page shows but no content. The same for if I start of the about page and go back to index

    • Claudia Romano

      Hi Nefertiti, give a look at what I replied to Antony Disez (comment below). That should help!

  • David

    Please help find the error or improve the script!

    The situation is this: if the second page is a script (for example, the appearance of the notice), then going to the first page of the script is loaded. For this to happen you need to reload the page.

    How to fix it?

    And thank you for this template. He’s great!

  • Joshua Barker

    First off, awesome.

    I have 2 pages with content that extends beyond the view port. I have a link at the bottom of the content. The transition works great, and loads in the correct content, but its scrolled to the bottom. Any tips on how to get it to load from the top? I tried using scrollTop() to no avail. I’m likely using it wrong though.

  • Gabriel Rosario

    how do you know so much?!?! Any book or school that you recommend? Please…

  • Grafyleens

    Hey Claudia. First off, this is awesome! And it’s been of great inspiration.
    As for my question, I guess I’m having a hard time understanding how you suggest we keep our content. Do we have to create multiple divs for different content? Or new full on pages? Or what?
    Hope this is easy to understand. If not let me know, and I’ll elaborate on my question.
    Looking forward to your reply. Thanks!

  • Benjamin Gordon

    Is there a way to have content sit outside the tags (eg. main navigation) that stays visible constantly and the section fades out / in ?

  • Benjamin Gordon

    Hi Claudia, Thanks for this :D I noticed that the transition doesn’t actually preload the contents of the next page. Is there a way to do this so that the loader doesn’t disappear until all the assets are 100% loaded into the DOM?

  • JWhiteford

    I’ve noticed this doesn’t work on targeted links within a page. It reloads the animation and doesn’t navigate to the target. Is there a way around that?

    • Claudia Romano

      Hi, make sure you added a data-type=”page-transition” to your link. That should do it.

      • JWhiteford

        HI Claudia, Sorry I mean that it reloads the whole page and doesn’t actually go to the target link. It does do the animation (with or without the data-type on the target link).

        • Claudia Romano

          Hi, I just tried to add a link (with data-type=”page-transition” and href=”index.html”) in the about.html page content and the transition works fine and loads the correct page (checked on Chrome and Firefox). I’d suggest to checking you have added a correct data-type and href. Hope this helps!

          • JWhiteford

            Sorry I’ve made this confusing. You are correct, the data-type works on which ever page added. The part I was having issues with is when you didn’t want the animation, only wanting the second page to anchor to a further down section on itself.

            Eg. You are on the home page and click to the about page. Now that you’re on the about page you click a target link to a location on the current page (this is where the animation is triggered again but isn’t wanted).

            Thanks for taking the time to respond to my question. I love your site and designs.

          • Claudia Romano

            Hi, I tried this too with no issue. Which browser are you using? Are you experiencing this issue with our downloadable files too? Thanks

          • JWhiteford

            Hi Claudia,

            Yes, I’m getting it with the files directly even. I’ve put up a repo to show you what I mean.

            The only thing I’ve added is the links on the “about.html” page.

            From the index page click into the about page. If you click any of the links I’ve added you’ll see how they don’t work. If you refresh that page then it works, but coming from an animated on breaks the targets.

            I’ve tested in Chrome and FF and neither work as they should.


          • Claudia Romano

            Thanks for the repo, I wasn’t able to replicate the bug! Just uploaded a new version which should fix the issue!

          • JWhiteford

            I was away on vacation so I didn’t get a chance to check this until now. Thanks for the update!!

  • Fabrizio del Gaudio

    Hi Claudia. Love all of your works. But I have a question: If I insert a google maps into a page (for example about.html) I can’t see the map if I come from index.html. It’s works fine only after refresh of about.html page. There is a solution for this?

    • Claudia Romano

      Hi Fabrizio, when you go from one page to the other, only the new content is loaded (not the scripts). So you should include your google maps script in the index page (or load it when you switch from the index to the about page). Hope this helps!

  • Kate Lim

    Hi Claudia, I’ve been trying to get this to work since Oct 3 which was right after your last bug fix. When I download it and run it on my local, it seems to fail to change the url from ~/index.html to ~/about.html hence fails to load the second page, and this is right after downloading the files so no changes were made by me. Any idea why this might be??

    • Claudia Romano

      Hi Kate, please give a look at what I replied to Antony Disez (comment below)

  • Thomas Savigny

    Hi Claudia, Thanks for this great work ! Juste a question : On one of the ajax loaded page, i have a form. The form is submit by ajax too. When i go directly to /contact.php, it work, but if i follow the link from another page, the form isn’t working. I read that you said : “when you go from one page to the other, only the new content is loaded (not the scripts)”. But all the js code are load on index.php, so i don’t understand the problem. Even by adding the scripts on the contact.html, it doesn’t work :( Thanks !

  • Yugesh Devarajulu

    hello Claudia….

    i have viewed your animation page its really good superb work done …

    after that i am interested and want to do the same transition in my page also i started to download the code and i have used it….

    but i faced the problem that..

    i have executed your page then its runs correctly but when i need to target to my page that means…

    Ex….(index.html— runs properly(urs page)…..then after running the loading bar its not redirecting to my page i.e.(main.html)..but in url it is changing some how i have done in ur coding but its not displaying my full page after ur css loading bar appears it remains blank…

    i hope u understand my pblm so please make me clear abt that ,…

    after loading bar it should redirect to my main.html page…

    thanks for giving such a wonderful animated page transition Claudia

  • peter nunn

    Hello Claudia, first let me echo the praise of the comments below. A lovely page. I am currently working in Firefox. I had some issue so i downloaded a clean copy of the files. I just changed the name of about.html to about1.html and although the page loaded it did not load correctly – the back link no longer worked and the background color did not pick up. A refresh of the page fixed the issue. I also noticed that the page was not working in Safari or Chrome (but i not that you have mentioned this below). Once again thanks for a fantastic animation. Any advice would be really appreciated.

  • cyphercorp

    Code doesn’t work when load second page even i put in localhost… please help…

  • Punit Bhandari

    Hi Claudia, great work on the code. I am facing two issues. 1. Not able to run the script on page load instead of on Button Press. 2. After the loader runs, it does not go on to the about.html file. Could you help regarding this?

  • Deiner David

    Hi is posible use this effect for ajax request success of failed ???? pls i need know

    • Claudia Romano

      Hi, the script uses the jQuery load() method, which allows you to use a callback function to handle a failed request. Cheers!

  • Valeri Crudu

    Hi Claudia! Love your work, great article! But I wonder if there’s a way to load the animation on page load? Thanks in advance!

  • Monisha Vachali

    Hi Claudia! The build when downloaded doesnt work… on click of start animation button only the background color of about.html is opened. Please help !! Thanks in advance.

    • Claudia Romano

      Hi there, give a look at what I replied to Antony Disez (comment below). That should help!

  • ichadhr

    Hi Clau, The download sample has strange behaviour, try load directly page ‘/about.html’ and click anchor

    (no animation) next try click anchor

    (animation triggered here). In this case I need to check whether the anchor has attr data-type.
    Thanks for posting it, as always make inspiration.

  • milad ahmadi

    thanks for your useful article.
    i locate the code on my local server and it works fine for me. but when changed this line of code:
    Start animation
    Start animation
    (“http://localhost/p/about.html” is absolute address of about.html on my local server)
    it does’t work efficiently. please help me

  • richardegil

    Has anyone determined if this technique is SEO friendly for crawlers?

    • Steven Perks

      The links are to the physical URLs so there’s no problem with SEO.

  • kapil

    really liked your design.
    I have a problem: the demo works great and the code works on firefox. But when I run it on chrome, it doesnt do transition from one page to another. It just gives a blank screen with the same bg-color of required html to be loaded. How can I fix this bug?

    • kapil

      I dont really get it why but I just uploaded the downloaded code on github and ran it from there. Now it works. Stiill dont know why local copy of the code is not allowed transition by chrome :/

      • Abhinash Jha

        Try using wamp or run it on some local server, it should work. It doesn’t work on chrome directly because of cross domain restriction.

  • Flávio Neto

    Really awesome work, surely you helped a lot of people by posting this! Thanks!!

  • Louis de Guzman

    Will it work with only the codes above or should I study the downloadable codes more? Thank you for your help

    Also, im using .php pages. WIll that be an issue?

  • Alvaro Gómez

    Hi, this demo looks awesome, i’ve been trying to implement it in a website I’m building but I have the following problems:

    1. When I go back to my home page, the image slider I have is broken.
    2. The other pages are taking the main css style even though I’m specific on my rules (should I try inline styling for some elements?

    I really hope you can help me. Thank you

    • blv

      Youll have to rerun any script or js instruction on each page load. Just measure your times and use classes with css3 animations to achieve a nice handling. About the css, we cant know without having a look, but that sounds like an error on your classes/id hierarchy. Watch your parent elements and the order of how your rules are declared.

      • Vikki

        Ho do you rerun the scripts?

      • Morten Stig Christensen

        How do you rerun the scripts? I have the same issue, that my scripts work, but only on refresh of the page. It’s like the page transition kills the scripts. Asking because I have tried everything, that I have been able to research myself, but nothing seems to work. They either kill the page transition script or work on page refresh.

  • Norman Dubois

    Pretty cool effect. Please make a course on building things like this! I’t would be really helpful :) Thanks

    • Norman Dubois

      Is there anything planned like this? It would help a lot! Thanks :)

  • Lukas Rauen

    I implented the markup, the css styles and and the js files.
    Im getting this error when Im clicking a link:

    main.js:53 Uncaught TypeError: section.load is not a function

    Can anybody help me?

    • Norman Dubois

      Looks like your section variable is not a jquery object. Try checking this line:

      var section = $(”);

      It should work. Also make sure that you’ve loaded jquery

  • Vikki

    Hey – I’m still getting an animation on my anchor tags linking to the same page.

    This bug “Bug fixed – animation wrongly reloaded with anchor tags linking to the same page”.
    Could you send me the fix? I’ve downloaded the latest version but still no luck.

    Thank you

  • The Jenggot

    hello all, if anyone can help me?
    there seems to be a problem, why do not want to index link text display on about?

    • Pavel Kolesnik

      You need local server to make it works
      You can use npm package http-server for this

  • Ravi Shokeen

    This is an awesome stuff. Thanks for sharing.
    Is it possible if we can animate the transition in such a way that the new page comes in sliding from left or right?

  • doomdidoom

    Is there a demo somewhere of this in action? With full final code?

  • Brad Lancaster

    Can you please do an advanced ajax course based on Ajax for UI and awesome page transitions. All the other courses out there do basic apps and nothing like this.

  • Anurag Nigam

    Thanks for this, I have been looking for the same..! Thanks again :)