33

I'm using css animations on my page and Safari seems to change unrelated font weights elsewhere on the page when animations are running. Any idea why this happens? All other browsers work fine, include webkit ones like Chrome.

I've detailed the bug in a video here - http://www.screenr.com/gZN8

The site is also here - http://airport-r7.appspot.com/ but it might keep changing rapidly.

I'm using compass (@transition-property, @transition-duration) on the arrow icons. No transitions applied on the heading that's flashing. On a Mac - so it might be the hardware acceleration, but I'm still trying to figure it out.

Sudhir Jonathan
  • 16,998
  • 13
  • 66
  • 90
  • possible duplicate of [-webkit-transform CSS Properties Hose Font Rendering](http://stackoverflow.com/questions/3396638/webkit-transform-css-properties-hose-font-rendering) – Sudhir Jonathan Mar 16 '12 at 14:20

3 Answers3

72

When you trigger GPU compositing (eg, through CSS animation), the browser sends that element to the GPU, but also anything that would appear on top of that element if its top/left properties were changed. This includes any position:relative elements that appear after the animating one.

The solution is to give the animating element position:relative and a z-index that puts it above everything else. That way you get your animation but keep the (superior IMO) sub-pixel font rendering on unrelated elements.

Here's a demo of the problem and solution http://www.youtube.com/watch?v=9Woaz-cKPCE&hd=1

Update: Newer versions of Chrome retain sub-pixel antialiasing on GPU composited elements as long as the element has no transparency, eg has a background with no transparent or semi-transparent pixels. Note that things like border-radius introduce semi-transparent pixels.

JaffaTheCake
  • 13,895
  • 4
  • 51
  • 54
  • 3
    This is a better solution. Thanks! – pixelfreak Nov 26 '12 at 21:06
  • Original poster, could you please consider accepting this answer? This solution has no negative side effects such as turning off font smoothing (big no-no for most of us). – jholster Apr 08 '13 at 05:46
  • Awesome. This fixed the same problem I was having in Chrome, when I was using translateX – jwinn Sep 25 '13 at 08:59
  • Wow. How did you find that solution? Just spent an hour trying to understand why animated elements affected __other__ elements. – jgthms Oct 05 '13 at 00:11
  • This solution won't work if you want the text to appear above the element you're animating in the z-index stack. In this case adding -webkit-font-smoothing: antialiased as stated below seems to do the trick. – Antfish Apr 28 '15 at 09:10
  • You, my friend, have done some great research. Thanks! – ansarob Jul 01 '15 at 04:32
37

Apparently, that's the price you pay for hardware acceleration: all text momentarily turns into images, which causes the drop in render quality.

However, applying html {-webkit-font-smoothing: antialiased} to turn off the sub-pixel anti-aliasing makes this problem go away. That's what I'm doing for now.

UPDATE: Since then, I've also come to learn that this happens only when the browser can't be sure if the section being animated is going to affect the text. This can usually be handled by having the text above (higher z-index than) the elements being animated, and/or making sure the text has a fully opaque background.

Sudhir Jonathan
  • 16,998
  • 13
  • 66
  • 90
  • This worked well, and the font we're using still looked great throughout the site. – Thane Brimhall Sep 14 '13 at 15:27
  • Thank you, i had a font that became bolder when i changed the background color from transparent to blue under Safari (only). – Georgio May 21 '14 at 08:02
  • This worked for me, but it didn't honour the font-weight of my typekit font. z-index worked good though! – Staysee Sep 26 '14 at 19:03
  • Thank you for this! I was animating an absolute positioned element behind other things, so I couldn't change the z-index without it overlapping the things on top of it. This solution fixed my problem without any regressions. – LordZardeck Dec 15 '15 at 22:52
8

I've faced this issue numerous times and have had success adding the following css to the animated element:

z-index: 60000;
position: relative;

It seems it needs both z-index and position to be effective. In my case I was using it with Font Awesome animated spinners.

mrkhyns
  • 109
  • 1
  • 3
  • 1
    This would work because the CSS hoists the affected element up into it's own layer. Because the z-index is so high, the GPU knows for sure that it will affect no other elements on the page and accelerates it without any side effects. – Sudhir Jonathan Jul 29 '13 at 11:46
  • @mrkhyns The reason that `position: relative` is necessary is that `z-index` doesn't work for `static`ally positioned elements. – John Kurlak Nov 11 '15 at 19:33