Hardware-Accelerated Page Transitions for Mobile Web Apps / PhoneGap Apps

I have been delivering a few PhoneGap Architecture and Performance talks in recent weeks. One of the performance techniques I talk about is –no surprise– the use of Hardware (GPU) Accelerated animations when available on the device. A typical example in a mobile application, is to hardware accelerate your page transitions. Even though this capability has been around for some time now, I still get a lot of questions about it. So I figured I would discuss it in this blog post.

Basic Infrastructure

Here is a typical set up for sliding pages in an out of the viewport in a mobile app:

The white box in the middle represents the browser viewport (the window through which the visible part of the document is seen): that is where the current page of your app is displayed at the full (100%) width and height of the viewport.

A page can be positioned to the left or to the right of the viewport by setting its “x” coordinate to -100% or 100% respectively (100% representing the viewport width). This can be done using two different approaches as explained below.

To slide a page from the right, you would:

  1. Position the page at the starting position of the transition (right)
  2. If needed, force a reflow to anchor the page at its starting position.
  3. Finally, position the page at the ending position of the transition (center) with the transition-duration style added to the page to indicate that it should be animated to that new position (see style definitions below).

In my own experience, I don’t have to force a reflow (step 2) when animating elements that are already in the DOM. However, I have to force a reflow when adding new elements to the DOM before animating them to their new position (see pageslider.js described below). More information here.

Here is a code example:

var homePage = document.getElementById("homePage"),
    newPage = document.getElementById("newPage");
// Position the page at the starting position of the animation
newPage.className = "page right";
// Position page at ending position of animation and add transition-duration
newPage.className ="page transition center";
// Simultaneously slide out the current page to the left of the viewport
homePage.className = "page transition left";

And here are two versions of the accompanying CSS: the first version will not hardware accelerate the transition; the second one will.

Non hardware accelerated transition:

Adding transform: translate3d(0,0,0); to the page will hardware accelerate the actual composition (drawing of the element on top of the background). However, it will not hardware accelerate the transition: The “left” property cannot be hardware accelerated. Changing the “left” property will force a layout every time the property changes (every frame).

.page {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);

.page.left {
    left: -100%;

.page.center {
    left: 0;

.page.right {
    left: 100%;

.page.transition {
    -webkit-transition-duration: .25s;
    transition-duration: .25s;
Hardware accelerated transition:

To hardware accelerate the transition, apply a 3D transform to the page’s x coordinate instead of changing the value of the left property. The version of the style sheet below should hardware accelerate both the actual composition (drawing of the page) and the transition.

.page {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);

.page.left {
    -webkit-transform: translate3d(-100%, 0, 0);
    transform: translate3d(-100%, 0, 0);

.page.center {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);

.page.right {
    -webkit-transform: translate3d(100%, 0, 0);
    transform: translate3d(100%, 0, 0);

.page.transition {
    -webkit-transition-duration: .25s;
    transition-duration: .25s;

Try the simple example below. The code is self-contained in simplepageslider.html. Right-click the sample and select “View Frame Source” to check it out.

PageSlider.js: A Micro Library for Simple Page Transitions

In a real-life application, you will typically want to generalize the process a little bit. For example, you could:

  • Automatically add new pages to the DOM and remove them from the DOM after they are animated out of the viewport.
  • Automatically determine the sliding direction based on the page history.
  • Provide a hook (using the webkitTransitionEnd event) for adding some logic when the transition completes.

I isolated that logic in pageslider.js, an example of a micro library you could use to provide hardware accelerated page transitions in your mobile apps.

Try the example below, or try it fullscreen here.

Source Code

The pageslider.js source code is available in this GitHub repository.

Hardware acceleration is not available on all platforms. Check out caniuse.com to see which platforms are supported. Make sure your animations work on platforms that do not support hardware acceleration.

32 Responses to Hardware-Accelerated Page Transitions for Mobile Web Apps / PhoneGap Apps

  1. sime March 19, 2013 at 4:47 am #

    Thanks for sharing this. I’ve yet to use translate3d, but if it speeds things along, I don’t see the reason why not.

    As far as I can tell (reading documentation and source) jQuery Mobile also uses translate3d and translateX,Y,Z for panel and page animations respectively.

  2. Matt March 20, 2013 at 5:25 pm #

    Full page demo works perfectly on my old iPhone4, very slow on Nexus10, with the transition not showing at all at times (and sometimes showing from the wrong direction)

  3. Ben March 21, 2013 at 4:54 pm #

    How could this be dropped into a Backbone app where the views are dynamically generated? Would you be calling slider.slide() from the Router ?

  4. Luis Abreu March 27, 2013 at 11:06 pm #

    You might want to change the html structure a bit.

    On bigger apps the reflow caused by the changing of classes might be too expensive.

    a) I’d suggest positioning each page in its final position, but with a wrapper, change the class only on the 2 pages you’re animating. Since they’re contained in their own absolutely positioned wrapper only those 2 pages will reflow, not all els (pages) on the same level.

    b) Since this is a predictable a/b animation, we can use keyframe animations instead to avoid having to force a reflow, to make sure the animation is consistent, more control.

  5. Juan Felipe Alvarez Saldarriaga April 3, 2013 at 12:41 am #

    app-UI also use this in his CSS, https://github.com/triceam/app-UI/blob/master/src/viewnavigator/viewnavigator.css, still, in android is sooooo slow, on ios it feels ok, but android is just a PITA, any workaround for android?

  6. Sir Kelsen April 15, 2013 at 1:04 pm #

    Excuse me, is there any kind of way to delete the transitions? I am making an APP that works as a ”quiz”, and depending on the answer, it goes to a page or other. The problem is the transition, my app does a flicker and i would like to avoid that. :(

  7. Federico González Brizzio May 20, 2013 at 1:43 pm #

    Hi Christophe,

    I’m using Page Slider, but I need to integrate it with BootStrap (responsive). “.page” with absolute position is a problem with container’s width (in px) ¿Have you any fix for this?

    Thanks! Federico, from Ushuaia, Argentina

  8. david June 17, 2013 at 6:24 pm #

    How to solve IE9 problem, since that doesnt support 3d

  9. czlowiek ze stali caly film June 29, 2013 at 7:10 pm #

    We’re a group of volunteers and opening a brand new scheme in our community. Your site provided us with valuable info to work on. You have done an impressive activity and our entire group can be thankful to you.

  10. Jeremy September 9, 2013 at 3:55 am #


    Great article – many thanks!

    Question – If my pages have different heights with scrolling in them, when I slide between pages, how do I maintain the scroll position of each page? For example, page A is 460px high and B is 700px. I slide from page A to B and then I scroll down B to the bottom of the page. When I scroll back to A, it’s also become 700px high and the bottom of A is shown. When I slide back to A, I want its original scroll position to have been preserved.

    Many thanks

  11. Hadrien September 19, 2013 at 12:32 pm #

    Hi, nice code thanks. I have an issue while running your first example on Android (as a compiled phonegap app I mean):

    I can scroll horizontally and thus display the right panel without clicking on the link. I’m facing the exact same issue on another app where I have div overflowing the screen. Any ideas on that?

  12. matt November 10, 2013 at 2:50 am #

    I like the idea behind your slider but I notice when inspecting the page in firebug that each time I navigate to and from a “PAGE” it reinserts the page so depending on how often you navigate to and from a page it adds it in again. is this going to be an issue?

  13. Tobias Sjögren November 18, 2013 at 9:07 am #


    I would really like to have the page transitions without jQuery, would it be possible for you exclude any bigger JavaScript file dependencies?


  14. johnny December 19, 2013 at 10:34 am #

    Hi Christophe, great article and very nice plugin. I want to thank you for all of your work. I’m very new to Phonegap and I’m not the fittest in Javascript. So your articles and videos were a good source for my learning process.

    Now I’m trying to combine pageslider.js with the native scroll from iscroll.js (version 5). I want to see if it works together so I mixed up together the code of your pageslider example on github with a simple iscroll 5 demo (barbone).
    I primarily want to run it on iOS. But I don’t get it to work. The native scrolling is not working. I think that it has something to do with the dynamic loading of the HTML content. So I tried to refresh iscroll. But I don’t know how to do that exactly. I’ve already tried a lot of solutions that I found in some forums but it’s still not working and I don’t want to use jquery mobile just for page sliding.

    Please can somebody help me?


  15. Marcin January 9, 2014 at 9:45 am #

    whether it is reasonable to use jquery address plugin for the construction of a mobile application where we load specyfic page when address is change ( we load pages and their scripts ) ?

  16. Africa January 13, 2014 at 1:50 am #

    Gud but not if you want to have dynamically generate pages…

  17. Nils January 22, 2014 at 1:35 pm #

    Cheers m8,

    big thanks for your solution. Up on this we build:

    - slide to pages with touch swipes
    - auto switch to pages by clicking menu item
    - animated mobile pagebrowser
    - integrated touch events with QuoJS

  18. vishant March 4, 2014 at 11:03 am #


    I have an issue with the simple pageslider on my iphone. From portrait to landscape back to portrait the page shrinks so the next page is also visible. Is there a fix for that?

  19. NSY March 20, 2014 at 4:08 am #


    Your work really saved my life, I been struggled for couple weeks due to my phonegap app is really slow and laggy….

    Is that any possibility to make the page swipeable?

  20. Lu March 25, 2014 at 4:42 am #

    I own the domain name HardwareAcceleration.net, I am selling it. Visit my website if interested.

  21. Sebastián Garzón March 27, 2014 at 11:04 am #

    Page Slider doesn’t work on my Android Huawei G610 the app doesn’t make anything. Don’t know why

  22. falkdav March 29, 2014 at 5:00 pm #

    Hi, Mr Coenraets, I have a problem (conflict) with your script and jQuery Mobile, this is my index.html

    Page Slider

    In Firebug log:

    TypeError: $ is undefined
    var slider = new PageSlider($(“#container”));
    ReferenceError: $ is not defined
    var slider = new PageSlider($(“#container”));
    How I can fix this problem?
    Thanks in advance!

  23. houstonwindowtinting.skyrock.com April 21, 2014 at 8:04 pm #

    hi!,I really like your writing very much! percentage we keep up a correspondence more about your post on AOL? I require an expert on this house to resolve my problem. Maybe that is you! Having a look forward to see you.


  1. Making PhoneGap Feel Native | Esa Juhana - March 31, 2013

    [...] Hardware-Accelerated Page Transitions for Mobile Web Apps / PhoneGap Apps | Christophe Coenraets [...]

  2. Sociogram Mobile: A Starter-Kit Application for PhoneGap and Facebook Integration | Christophe Coenraets - April 16, 2013

    [...] PageSlider [...]

  3. Days till Dead – Android App built on PhoneGap - Jae Subramoney - May 28, 2013

    [...] used Christophe Coenraets Pageslider. This guys info is awesome. You need to read all this suff and watch his videos. [...]

  4. Phonegap and Android overflow issue | BlogoSfera - October 10, 2013

    [...] at all about overflow:hidden css property when having overflowing divs. I took the code of a great tutorial on GPU transitions with HTML/CSS and add it to a simple phonegap project [...]

  5. Phonegap and Android overflow issue | Ask & Answers - October 29, 2013

    [...] at all about overflow:hidden css property when having overflowing divs. I took the code of a great tutorial on GPU transitions with HTML/CSS and add it to a simple phonegap project [...]

  6. Parallax UI for PhoneGap and Mobile Web Apps | Flippin' Awesome - December 23, 2013

    [...] to another is achieved purely using hardware accelerated CSS animations and transitions. Check out this example from fellow Adobe evangelist Christophe Coenraets for detail how the hardware accelerated page transitions were [...]

Leave a Reply