t5ghhw
Last Updated: August 18, 2016
·
10.16K
· xtagon
B51e7cdcc7a02568f78c50c5eeee2439

Animated Page Transitions in Rails 4 Apps

If you're using Turbolinks in your Rails app, which is default in Rails 4, you can add a neat little page transition animation. No jQuery required!

If you want a quick demo, just try using the navigation menu at http://www.xtagon.com/

There are probably many ways to do this, but here's how I did it.

The HTML

You might want to decide which portion(s) of the page to animate. In my case I animated everything but the header and nav bar. For this example, give one of your elements and ID of primary-content and everything inside it will be treated as the main content to transition.

The CSS

We're going to use the wonderful animate.css for our transitions. Play around on their website until you find a transition you like, then create a custom animate.css file. Drop that bad boy into app/assets/stylesheets.

The JavaScript

Animate.css works by adding the animated class to an element, along with the class for the specific animation you wish to perform. What we want to do is hook into Turbolink's page:fetch and page:change events to start the animations when the page changes.

Save this bit of JavaScript to app/assets/javascripts/turbolinks_transitions.js and make sure it's required in application.js.

document.addEventListener('page:change', function() {
        document.getElementById('primary-content').className += 'animated fadeIn';
});
document.addEventListener('page:fetch', function() {
        document.getElementById('primary-content').className += 'animated fadeOut';
});

And here it is in CoffeScript, if that floats your boat:

document.addEventListener 'page:change', ->
        document.getElementById('primary-content').className += 'animated fadeIn'

document.addEventListener 'page:fetch', ->
        document.getElementById('primary-content').className += 'animated fadeOut'

That's it!

Restart your Rails server, load the page, and off you go!

Say Thanks
Respond

11 Responses
Add your response

10185
4693d7cfa88635d430c0de9a92f8dd84

Nice tip, Btw, I checked out your SoundCloud; cool music my fellow musician/coder!

over 1 year ago ·
10189
B51e7cdcc7a02568f78c50c5eeee2439

Thanks! You've got some pretty sweet sounds yourself.

over 1 year ago ·
10233
4693d7cfa88635d430c0de9a92f8dd84

Thanks!! I've been working on new stuff, can't wait to upload the finished versions :)

Btw, I hope to visit Oregon one day. It seems like the best place to live :)

over 1 year ago ·
13046
E9b3cd1aa48e98fbdf695a7d862224e0

Hey Great post! Thanks. I am wondering if you can think of a way to bind the transitions differently, based on the page that is being changed.

For example, If I am on a homepage and go to projects index it will slideInRightBig & going back home will slideInLeftBig.

However if I select a project show from the index, the index will slideOutDownBig & going back to index will slideInUpBig - any thoughts?

over 1 year ago ·
13048
B51e7cdcc7a02568f78c50c5eeee2439

@serknight, it would be trivial to change the JavaScript code to animate elements based on a data-transition-in and data-transition-out attribute set on the element(s) you wish to transition. This would solve the problem of wanting to animate more than one element, and animating different elements different ways on different pages.

However, it sounds like what you actually want is to set the transitions based on the context of your navigation. That's a bit more tricky. You can transition out based on which link you've clicked, by tagging certain a elements with a data-attribute to describe which transition you want for that link. But how would the next page know which transition in to use? You could use a cookie, a GET param, or pass the Referrrer header. It sounds possible, but I don't think it would be very clean.

Another idea is to use meta link elements as context when applying the transitions. For example, an article might have multiple pages. You might want <link rel="next"> to animate one way and <link rel="prev"> to animate another way. Still, you would need a way to know which transition in to use on the next page when it loads.

over 1 year ago ·
13054
E9b3cd1aa48e98fbdf695a7d862224e0

Thanks for the response. Yeah I continued with it, using turbolinks and got further down the rabbit hole.

I found out that turbolinks does not save the window.referrer so I could not bind the next transition based on the referrer. I tried setting a global js variable, but the way the turbolinks/coffeescript was set up was overwriting the variable every transition. Back to the drawing board. I think I will add meta-tags to specific links and use those to bind which transition I will bind.

Thanks for the response. & once again, thanks for the OP.

over 1 year ago ·
14147
B51e7cdcc7a02568f78c50c5eeee2439

@serknight, when you solve it, be sure to make your own pro-tip :)

over 1 year ago ·
18024
B714dbd934173ab40af94af5b549a371

Thanks for this! It saved me a good chunk of time not rebuilding pages into one page and doing goofy JS stuff. It would wonderful to see this in a gem that compiles only the animations used and have data- support.

If your animation wrapper has an existing class (say "container") and you're using native JS, don't forget to add a space before "animate" when adding that class.

In addition to the issue @serknight mentioned, I'm getting some choppy fadeInRight animations due to the page loading, then the animation starting. Any suggestions on how to get a smooth animation?

over 1 year ago ·
18027
B51e7cdcc7a02568f78c50c5eeee2439

@archonic The issue is that 'page:change' might be fired before the transition out animation has a chance to finish. I'm sure there's a way to get it right, but I'm not quite sure how.

over 1 year ago ·
18029
B714dbd934173ab40af94af5b549a371

@xtagon It sounds like the transition in animation event listener should be listening for the end of the transition out animation (in addition to the content being available after the request). I don't think CSS3 can do that, but I know greensock can.

over 1 year ago ·
18030
B51e7cdcc7a02568f78c50c5eeee2439
over 1 year ago ·