- Posted on: Sep 4, 2010
- Tag: mobile dev
- Reactions: 23
> You shall not flicker!
Off screen items on iScroll are not cached by the mobile browser, when it comes their turn to appear on screen they need a few moments before being accessible, creating a nasty flickering. Well, there’s an easy trick to force the browser to cache all elements and it’s so simple I regret not having tried it before.
This flickering is a well know “feature” to all iScroll users. Have a look at this example (only on real device! no simulator). I added some background images and text shadows to emphasize the flickering. The effect is less noticeable on iPad and newer devices, but still it makes the application feel less “native”.
Now have a look at the flicker free example. The only difference between the two is that in the flicker free version I’m applying -webkit-transform:translate3d(0,0,0)
CSS style to all elements inside the scrolling area.
Why isn’t this going to be included in the main iScroll script? The answer is: memory allocation.
We do not have control over memory in mobile webkit. If we use too many resources the browser just crashes, and of course if you have thousands elements inside the scrolling area, forcing the browser to cache everything, would just make your application crash.
So that’s why you should optimize your application and use the -webkit-transform
trick sparingly.
Also try to keep your HTML structure as simple as possible. Remember that the following:
<ul> <li><a class="somewhere">Some text</a></li> </ul>
Can be always replaced by:
<ul> <li>We just lightened the HTML structure by 50%. If you have 100 rows, you’d have 100 tags instead of 200. (And of course I’d use even listeners instead on inline
onclick
.
You should also look into -webkit-backface-visibility to minimize the flicker issues.
yes, it works with many other properties as well, the bottom line is to force the CSS HW layer over all objects in the scrolling area. But the memory problem still remains.
In my opinion that problem should be par for the course and you should enable it anyway. There’s no way around the issue, and anyone that nests enough elements to encounter the memory issue will want a workaround for the flickering anyway.
Or perhaps it can be an opt-out setting.
True, it could be an opt-out, or maybe opt-in feature (
chache:true
?). Only if we had memory management…“Iโm applying -webkit-transform:translate3d(0,0,0) CSS style to all elements inside the scrolling area.”
Why not apply it to elements before they enter the visible area but not all so it would cache the visible elements and soem above and below?
Or would the detecting whats visible and constantly applying that to things cause a performance issue too.
I’m afraid the engine is not powerful enough to do such an on-the-fly task.
… but I’m wondering… maybe we could just apply the translate3d() to elements one by one at start-up and remove it right after. It might be enough to let the renderer cache the out-of-the-screen elements. I’ll try this later today.
Update: unfortunately setting and unsetting the webkit-transform does not work.
What about applying it on the next three elements rather than all?
Thinking about it now, for smaller things (like a thumbnail sized image), maybe making the image a sprite might be better? I guess it depends on the image you’re trying to use if it’s worth the performance trade off
should be applied to all upper most element in the tree. Eg:
DIV —-> UL —-> LI —–> SPAN
just to the span.
I want to know is there away to do what many applications like twitter and seesmic do, when you scroll up to the very very top and release it loads new data?
sure of course it’s possible… must be coded, but definitely possible it would be an interesting tutorial.
Great post. Your QR code on the main project page has me spoilt, it would be nice for these examples too
Also, it looks like you have a typo on 153 on noflickering.html.
Thanks for sharing! This flicker thing is really annoying! Doing animations with JavaScript is not as smooth as webkit-transform, but it’s better than the flickering …
How would you use event listeners instead on inline onclick?
stackoverflow.com/questions/5330553/list-of-links-using-event-listeners-to-keep-my-html-structure-as-simple-as-possi
Thanks for this info. I have tried to apply this to https://gist.github.com/333492 but it doesn’t seem to make a difference. I changed line #2 to:
var strAngle = “translate3d(0,0,0) rotate(” + angle + “rad)”;
Any help is appreciated thanks.
Never mind. I realised I needed to have a transition applied. In fact, I believe the pendulum can be entirely CSS3 with no JavaScript so I’ll keep hacking away at that.
Wow, exactly the thing I was searching for!
Thx for your blog posting
You have a spelling error in your css selector property.
-webkit-ransition-duration
Didn’t like that onclick thing. If you’re sacrificing semantics over performance, why not ommit the ul and li tags and put a lot of a tags inside a plain div?
Good old plain links are still better than onclicks. You can style them uniformly, the user can open it in a new tab, search engines can calculate page ranks and so on.
Thank you!!! I’ve been trying to solve this for about 10 hours. Much appreciated, worked perfectly.