Web browsers weren't really developed with DOM-based animation (that is, using native HTML elements) in mind; repositioning and re-rendering an image or <div> element within any document means that a certain amount of "reflow" has to happen, where the browser must not only re-draw but also do some calculations to determine if and how the repositioned element has affected the flow of nearby elements and the overall document. This logic is also seen in action when fluid sites dynamically rearrange themselves to fit one's browser window when being resized.
Now, being curious about this, I started making some benchmarking tests, to see if I could avoid these reflows. Some websites talked about having several DOM changes after each other might avoid additional reflows, because the browsers waits to see if several DOM changes happens at once, allowing the browser to apply them all in a single reflow.
So, I created a big animation thingy, with 200 objects flying around, and I take the time before and after the code has looped though each object, animating it for that "frame" or "loop" or whatever you want to call it. This was going to be my base, onto which I would try different optimizing tricks. It displays the amount of milliseconds between each grapical loop.
However, I was a bit amazed, because despite those 200 objects flying around, my benchmarking shows that looping though all these objects takes...10 milliseconds.
Now I was kinda confused. I'm running on Linux, so I don't have IE6 to test with, I did this test in FF3, which might explain it, but still. I'm kinda confused. This performance is so good that I don't really need any optimizing at all!
I too am interested in the reflow issue. If the elements you are moving around is positioned absolute then those element should not effect the document layout...and changes to those should not cause the entire page to reflow.
I'm not 100% sure on this but it does make sense. If you can verify it or have another explanation I would like to know.
Hmh. That's a good point. Absolute elements shouldn't have any effect upon the document flow, at least in theory. It wouldn't surprise me if Firefox and Opera handles this well, while IE6 and such screws up.
Anyway, I'm thinking of making a system where I measure the browser strain (and thus asynchronous work too), by having a timeout fire very frequently, and then messsuring how delayed it is (which I have experienced when there are lots of things happening in the browser).
This is very interesting, because Opera describes that there are two different things that can happen, a reflow, and a repaint. A repaint happens when you change something that doesn't affect the layout of the document, like for example changing the background color of an element. It also talks about how absolutely and fixed elements do not force a reflow upon the whole page, but only the object itself (and that probably due to that even an absolutely positioned element can contain child elements that act according to a flow).
This is very good for us, because it means not only that absolutely positioned elements saves us from most of the pain when it comes to reflows, but also that we can sometimes avoid reflows entirely, and only be bothered by it's baby brother, the repaint.
One prime example for this would be when one has an animation. I'm not quite sure what makes a repaint and what makes a reflow, but, one could think that changing the src of an image tag rapidly to animate it produces a reflow, due to images having diffrent sizes. Perhaps browsers are smart enough to avoid reflowing an image that has a set size, but I doubt it. What, however, we can do, is use the overflow animation trick, which I will not go into detail with here about. I highly suspect that this does not produce a reflow, but a repaint, but I can't be sure (and it's damn hard to test -_-)
The site explains that Opera doesn't do reflows for every DOM change. It tries to wait until the script thread is over (if you don't know what this means, just know that lots of DOM changes after each other will be treated with one single reflow). The exception to this is if the thread takes too long to execute, pushing out the reflow too much. Opera will in this case do the reflow forcefully.
I currently have no information about other browsers than Opera. My gut feeling tells me IE doesn't do this very nicely, but I'm not sure about Firefox. Could go both ways.
I'm working on my testing example, to see if doing these things will help the strain on the computer any (trying to bunch up the DOM manipulations to happen all at once). I shall post here with my results.
I've made a bunch of tests, which you can see here.
The "Display Enchantment" works by setting the css style display to "none" right before all objects are updated, and then back to "block" when all objects are finished updating for that loop. This was recommended on the Opera website, but I see no improvement at all.
It could be that the display enchantment only helps when you aren't absolutely positioning elements. But I'm too lazy to check that, because, it's pretty rare that you have moving objects that are not absolutely positioned or fixed. Almost impossible, I'd say.
The "Swap Enchantment" works by removing the world object (the big green block) right before all objects are updated, and then adding it back to the body after all objects are finished updating for that loop. I was expecting flicker from this method, but there was none (but flicker may result in other browsers than firefox). This method actually made things worse. At 800 objects flying around, I noticed a slight slowdown when using this method.
I've yet to come up with any more ideas for how to avoid unnecessary reflows and repaints, but I'll add any suggestions you guys might have.
Oh, and please do my test in your browsers, and report back if there is anything interesting happening.
Soon, Firefox will allow you to detect a repaint as an event. Although this isn't very usable for web development in general (unless you use it to make Firefox specific enchantments), but, I think it would be awesome to test how repaint behavior in general work (or at least for Firefox)