Jank free, at last!
Creating a smooth scrolling experience
Over the last few months I've worked on a few different interactive case studies. I guess what you’d call Parallax sites. The kind of page where things move around as you scroll. As it turns out these are quite hard to get jank free (Smooth, without lag or stuttering) as even a tiny hiccup is very noticeable when the page is scrolling.
It’s forced me to put a lot of time and effort into performance and optimising animations. It’s turned into a bit of an obsession, so here’s a couple of learnings and advice on this topic that might be of help when planning out future projects like these.
I think being aware of the pitfalls during both the conception and design stages can remove a lot of potential challenges of the development.
Jank is the result of frames taking too long for a browser to make, and it negatively impacts your users and how they experience your site or app.
For a smooth experience the website needs to run at 60 frames per second, which is the refresh rate of most monitors. Anything less, especially below 30fps feels slow and jittery. Again, this is especially noticeable when scrolling down a page with animations.
60fps means the browser has 16ms to do all the work involved in writing 1 frame to the screen. That’s not a lot of time, so to reach that goal there’s a few things we should consider when designing and building these applications.
Firstly, if you’re a developer, before you go and build one of these sites I’d recommend you go and read Scrolling Performance by Paul Lewis and High Performance Animations by Lewis and Paul Irish. (I wish i had!)
Otherwise, here’s some of the biggies I've come across.
What to animate
In general, the only things that should be animated if you’re going for 60fps is position, scale, rotation and opacity. The good news is with these 4 combined you should be able to do pretty much anything you could do otherwise.
I learned this the hard way. I started out animating margins and top-positioning of elements. this didn’t feel as smooth as it could have been if i had used positioning instead.
There’s a few gotchas to this approach, so go read High Performance Animations for the full story.
Scaling of large images:
This is a bad idea. It’s extremely resource intensive and will definitely be noticeable for the user. Moving images around with translate is fine, but scaling things during runtime is very risky.
// This will trigger a resize when the image becomes visible.
If you need different sized images, use some sort of responsive image solution to prevent scaling images during runtime.
If you want to maintain 60fps you really want to avoid resizing images during runtime activities like scrolling or animations; they are seriously expensive.
- Paul Lewis
An example of this was a site i worked on where as you scrolled down, a large image appearing caused a significant lag just as it became visible.
On the key frame where the cloud image had to be written to the screen. The browser also had to then resize the image to fill 100% of the screen size. All that work took the browser just over 60ms. That’s about 3 frames, (17–18fps), and felt like a short freeze when scrolling.
Lots of stuff going on at once:
This one is a bit tricky. The more stuff is being animated at once the slower the experience is going to feel. There’s a lot of ways around this, and even animating a few objects can give the illusion of lots of movement. For example, the first slide on the Oakley “moto” site only have 5 moving elements. I’m not saying there is a hard limit. In fact, if you follow “what to animate” the limit is much higher!
Use the dev tools:
The Chrome dev-tools provide a lot of really useful tools for diagnosing what’s slowing your page down. For starters, in the “Rendering” options, turn on “Show paint rectangles” and see how much of your page is repainted as you scroll down. Use the above “what to animate” rules to get rid of as much green as possible.
The “Timeline” is also extremely useful, and provides a frame-by-frame view of page rendering. This can also be used to find out what is causing Jank.
Click the record button, interact with your page and click again to display the results. Below we can see that an image paint is causing a huge spike in frame rate.
Plan out what will happen on mobile. I mean, really plan it out. Even if mobile isn't to be supported, chances are a large volume of traffic is going to be from a phone/tablet. What experience do they get?
Performance-wise, anything even slightly resource intensive will run like a hog on older devices, including the iPhone 4 and the iPad 2. According to Apple (half a year ago, at least), the iPad 2 alone accounts for almost 30% of the user-base.
Most sites of this sort that I've looked at fall back to a static version of the site on tablet/mobile, without any interactive business. This is a shame, but for these sites- at least until the hardware catches up- this seems to be the standard solution.
Speaking of mobile, old hardware are in much the same position. I ran the first site i built on a 3-years old laptop and wanted to cry. When you go down this road, unless you keep the animations very lean, there will be a lot of users that has a terrible experience with your site.
Avoid scaling large images on scroll. Be clever about what you animate. Use position, scale, rotation and opacity. Dev-tools = awesome. Plan out the mobile experience from the start and be aware that you’re probably going to be screwing users on old hardware.
In a near future, with the web animations API and the CSS will-change property making it into browsers, some of the above points will be resolved.
Until then though, keep these things in mind and you’ll be Jank free!