App-like Scrolling and Transitions with Ember.js and Liquid Fire

Isaac Ezer
Jan 17, 2017 · 6 min read

The consulting company I work for, 201 Created, recently built a proof-of-concept Ember.js app that showcases the extraordinary capabilities of the modern web. Many native mobile apps use subtle animations during transitions to create a seamless user experience, and we wanted our app to feel just as good. Luckily, the web provides great animation tooling with CSS and JavaScript.

The demo is at https://www.shop-201.com. To keep up with our progress, follow @isaacezer or @two_oh_one on Twitter. Here’s a screenshot:

Screenshot of shop-201.com

Ember.js and Liquid Fire

We love Ember.js, and it’s a great framework for making single-page apps that have a mobile-like feel, so we used it for our app. For animations, we used an excellent animation library for Ember called Liquid Fire, which is maintained by Ember Core Team member Edward Faulkner. We also used two of Ed’s add-ons, Ember Elsewhere and Memory Scroll, which help with some common Liquid Fire use cases and are great learning resources. Thanks, Ed!

Inspiration From Native Apps

I wanted to find an iPhone app that uses animation in a way that creates a more seamless experience for the user, without being distracting. I was particularly impressed with Groupon’s iPhone app. Take a look at this screen capture. Here are a few things that I noticed and wanted to replicate:

  1. The header and footer remain fixed while scrolling, and contain different content depending on the context. When the context changes, the toolbars fade out and in with the new content.
  2. When I click on an image in the list view, it stays visible and floats into its place at the top of the detail page.
  3. When I click to go back to the list page, the app remembers where I was in the list.
  4. There’s a two stage animation where first the images moves into place, and then all the new content on the detail pages fades into view.

In the next sections I’ll show you how to implement each of these steps.

Ember Add-ons

As mentioned above, Edward Faulkner has also created excellent add-ons which help with common Liquid Fire use cases. The first add-on that I found useful was Ember Elsewhere. This allows you to render content anywhere in the DOM, which is handy if you want to render content into fixed headers and footers as you navigate the app. The second is Memory Scroll, which allows your app to remember its scroll position. This was my first time using Liquid Fire, and reading the code for the dummy apps that ship with these two add-ons really helped me understand how I should layout my application and how I could get Liquid Fire and these add-ons to work together to do exactly what I wanted.

This is what the Ember Elsewhere dummy app looks like:

Ember Elsewhere Dummy App Screen Capture

And here is Memory Scroll:

Memory Scroll Dummy App Screen Capture

Combining these two add-ons will give us many of the effects that we liked in the Groupon app.

1. Animation in Fixed Toolbars

To start with, we want an app with a fixed header and footer, a scrolling window in the middle, and some dynamic header content that animates when we change routes. Here’s what it looks like:

The code without the animation is in this twiddle. With a few modifications to use liquid-fire and ember-elsewhere, we can get the header animating as the route changes. Here’s the twiddle for that. Look at the use of the from-elsewhere and to-elsewhere helpers, as well as the animationRules defined in the ApplicationController.

A word on Twiddles

Ember Twiddle is an amazing tool for writing and running Ember.js apps right in the browser. At the time of writing the latest version of Liquid Fire doesn’t work in Ember Twiddle. Therefore all my examples use Ember 2.5.1 and Liquid Fire 0.25.0. The code works with the latest version of both Ember and Liquid Fire as a standalone app. I’ve raised the issue and have been assured that there is a fix on https://canary.ember-twiddle.com and it will be released soon.

2. Animate the product from the list to detail page

We’re going to use Liquid Fire’s explode & fly-to animations to move the product from its location on the index page to the detail page. Here’s what it looks like:

FlyTo Screen Capture

Again, here’s the twiddle. The key changes here are in a new file called transitions.js which define the transitions. Both the index.hbs files and item.hbs need to set a data-item-id attribute on the node containing the item so that Liquid Fire knows which nodes are related. Also, since we’re animating the route transition, we need to change the {{outlet}} in application.hbs to a {{liquid-outlet}}.

3. Memory Scroll

Now, reduce the height of your browser window so that only the first five products are visible without scrolling. If you click on Product #5, and then click “Back”, notice that the product animates smoothly to the detail page and back to its proper place in the list.

Now scroll down and click Product #9, and click “Back”. Notice what happened? When you return to the index page, it’s back to the top of the list. The app doesn’t by default remember you that you were scrolled down to Product #9.

We can make it remember using Memory Scroll. Again, here’s the twiddle. To use it, wrap your scroll area by invoking the {{#memory-scroll helper and giving it a unique key for that area.

Here’s what it looks like:

Memory Scroll Screen Capture

Helpful tip: I found the following CSS made it a lot easier to reason about the positioning of DOM nodes that we’re being rendered inside Liquid Fire outlets. It’s probably a useful thing to set as soon as you install Liquid Fire.

.liquid-container, .liquid-child {
width: 100%;
height: 100%;
}

4. Delayed Animations

A nice finishing touch is to make the flyTo animation for the product happen first, and then the animation for the title header to happen after. In our transitions we set a duration of 400ms, so to get this effect, we can set a delay on the header transition equal to duration of the first animation on the flyTo.

Open the ApplicationController where animationRules is defined, and change line 14 to this.useAndReverse('fade', { delay: duration, duration }) . Notice that Ember Twiddle even supports ES6 features such as property shorthand! Here’s the twiddle and here’s what it looks like:

Wrapping Up

As you can see, Liquid Fire is a really powerful tool that allows us to create seamless transitions in our web apps that look great on desktop and mobile. Ember and Liquid Fire give you powerful primitives for building web apps, and the source code for Ember Elsewhere and Memory Scroll are great examples of how you can compose those primitives to do incredible things!

Here’s the twiddle for the final product.

Need help adding animation to your Ember.js app? Say “Hello” to hello@201-created.com.

Further Reading

These tutorials on Liquid Fire, written by other folks in the Ember.js community, were very helpful when I was starting out:

Finally, here’s a link to the Liquid Fire Interactive Documentation.

Isaac Ezer

Written by

Ember.js coder living in New York. Lindy hopper and jazz addict.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade