10

I am using some really simple CSS3 transitions in my app like in the following example where I try to slide in a div container from left to right:

<div id="navi">
    <form>
        <input>...</input>
    </form>
    <ul>
        <li>...</li>
        <li>...</li>
        <li>...</li>
        <li>...</li>
        <li>...</li>
        <li>...</li>
        <li>...</li>
        <li>...</li>
        <li>...</li>
        <li>...</li>
        <li>...</li>
        <li>...</li>
    </ul>
</div>

<div id="bg">
    <img src="...">
    <img src="...">
    <img src="...">
    <img src="...">
    <img src="...">
    <img src="...">
    <img src="...">
    <img src="...">
    <img src="...">
    <img src="...">
    <img src="...">
    <img src="...">
</div>

#navi{
 z-index:2;
 position:fixed;
 -webkit-transform:translateZ(0);
 -webkit-transform-style: preserve-3d;
 -webkit-backface-visibility: hidden;
 -webkit-transition:left 0.5s;
 left:0;
 top:0;
 bottom:0;
 width:95%;
 overflow-x:hidden;
 overflow-y:auto;
 -webkit-overflow-scrolling:touch;
}

.slidein{
 left:500px;
}

To slide in/out the div I do:

$("#navi").toggleClass("slidein");

On my iPhone 4s this transition is very smooth. On an iPhone 4 performance is horrible.

Is there anything that I can do to increase performance? Are there any "golden rules" or best practices?

So far I only know of:

  • Use -webkit-transform:translateZ(0) to trigger hardware acceleration
  • Use -webkit-transform-style: preserve-3d;
  • Use -webkit-backface-visibility: hidden;
  • Avoid gradients
  • Avoid box-shadow

One of my main problems is that there are quite a lot of items inside #navi like a <ul> with many <li> elements. Underneath #navi there is a also another div element with quite some large images. These seem to decrease performance as well (At least performance goes up when I use display:none on them but that's not an option since they need to be visible during the slide transition).

syntagma
  • 23,346
  • 16
  • 78
  • 134
Timo Ernst
  • 15,243
  • 23
  • 104
  • 165

1 Answers1

11

Try to animate transform instead of left property, it works really smooth even on old iOS devices.

#navi {
  transition: -webkit-transform .5s ease;
  -webkit-transform: translate3d(0, 0, 0);
}
#navi.slidein {
  -webkit-transform: translate3d(500px, 0, 0);
}

Fiddle: http://jsfiddle.net/x8zQY/2/

2017/01 update: Please read this great article about animation & GPU rendering, profiling and optimising techniques https://www.smashingmagazine.com/2016/12/gpu-animation-doing-it-right/

syntagma
  • 23,346
  • 16
  • 78
  • 134
antejan
  • 2,594
  • 12
  • 15
  • Nope, that doesn't do it. Using `translateZ(0)` and `left` property gives the same effect as your proposal. – Timo Ernst Jan 14 '13 at 17:45
  • Hm, can you open my fiddle on device and push the button several times? I get on iPhone 4s something like 2-3fps for the first square and smooth animation for the second one. – antejan Jan 14 '13 at 18:00
  • Yes, that's because you need to add `-webkit-transform: translate3d(0, 0, 0);` to `box1` to enable hardware acceleration ;-) – Timo Ernst Jan 15 '13 at 10:06
  • Do you have the same result on iPhone 4? – antejan Jan 15 '13 at 10:47
  • Damn, you're right! I tested on iPhone4 and using `translate3D` is a lot better than doing the transition via `left`. – Timo Ernst Jan 15 '13 at 15:03