Two months ago, I left my job at Mozilla to tackle an emerging challenge on the web today: getting peer-to-peer video chat right. I have transitioned from C++ browser platform work back to web technologies. It’s thrilling to reap the benefits of all the progress we’ve made in the browser over the past few years. It may not be perceptible to web developers who have been in their element for the last three years, but it’s striking to me how much the needle has moved. One thing that has not changed: all the crazy-ass browser workarounds!
Our designer pointed out today that Safari was re-rendering text when CSS animations were active. The affected text was not related at all to the animation. Putting a background color on the text block fixed the issue:
I don’t know why this worked, but I have a theory. CSS transitions and animations are hardware accelerated in every browser today in some form or another. Every browser now has to balance complex rendering algorithms with performance, and sometimes they don’t get them right. For Firefox, we broke apart web pages into pieces called layers. The content of the layers were rendered in software, and at a later point all the layers are composited using hardware acceleration to give us what we see on our screens.
Does Firefox create a new layer for every single block element? No. There is a cost to creating a layer, so Firefox keeps layer creation cheap and makes them on the fly, for instance, when CSS animations are running. When it creates this new layer, the software renderer has to repaint some elements on the web page. The final bitmap dimensions change because the larger paint has been broken up into two paints that will be composited together. Good text rendering is heavily dependent on subpixel positioning, so if you aren’t careful the aliasing calculations will subtly change when rendering text.
Safari does something similar through the Core Animation framework, so my guess is that setting the background color changed the regions that the software renderer painted and stopped tickling the bug. Background color permits Safari to paint that div to an opaque ‘layer’ instead of a transparent one, or so it goes in my head.