You read that right. Tested on multiple machines in the office and the only difference between scenarios was browser size. A coworker narrowed it down to a 2000px sweet spot. Lo-and-behold when we each resize our browsers to be >= 2000px wide and mouse over an element with a transform animation various elements on the page — specifically any element with a CSS gradient background — will flicker. Inversely, if you resize the browser to be < 2000px wide and mouse over that same element no flickering occurs.
Anyone else seen this bizarre behavior? Why is 2000px a magic number, and what exactly happens at 2000px?
NOTE — I can't really share screenshots/video/links as this site isn't yet public, and code is relatively unnecessary as this seems to be more of a browser issue than anything.
NOTE 2 — My question here is really around what exactly happens in Safari at 2000px, not necessarily how to fix the flicker with backface-visibility
or translateZ
or the like. Reason being that we use -webkit-font-smoothing: subpixel-antialiased;
liberally throughout the site and using any of these tricks trumps that property for the entire page, turning on antialiasing / grayscale for all text.
EDIT — Okay, sorry for not having done this earlier. Here is a bit of code in a jsFiddle that should reproduce the issue: http://jsfiddle.net/brandondurham/ujPMK/embedded/result/
Remember, Safari has to be set to at least 2000px wide for this to happen.
Frustrating huh?
See EDIT4 for the answer to why 2000px is a magic number.
There is a couple of things you can try.
Add -webkit-transform-style: preserve-3d;
to the elements that are
flickering.
add -webkit-backface-visibility: hidden;
to the elements that are
flickering.
move the animating element outside of the parent the flickering
elements are within.
EDIT —
Wesley Hales, said here
"I encountered glitchy behaviour when applying hardware acceleration to parts of the page that were already accelerated"
Its hard to help you debug this without any code. But for starters I suggest you turn on debug mode in safari. Write 'defaults write com.apple.Safari IncludeInternalDebugMenu -bool true' in the terminal.
After this a Debug menu will show up. Choose Drawing/Compositing flags > Show Compositing borders.
This will help you see whats being rendered and by that choose what to put in hardware acceleration and what to leave out.
EDIT2 —
This is worth checking out as well: fast-animation-with-ios-webkit
Its regarding iOs, but I've experienced that - in some circumstances - solutions that work on iOs also works on osx.
EDIT3 —
If you are just asking what happens when its bigger than 2000px I can tell you for sure that on iPhones, WebKit creates textures that are no larger than 1024 by 1024, and if your element is larger than that, it has to create multiple textures.
Documentation on texture limitations
Now, when they do it on iPhone, it wouldn't surprise me if they do the same on OsX, but has a higher limit.
Don't know if this is your case tho. Impossible to tell without any code.
EDIT4 —
"The implementation in TextureMapperTiledBackingStore is pretty simple, and is used only to work around the 2000x2000 texture size limitation in OpenGL."
So, if your element is bigger than 2000x2000 it has to create multiple textures.
http://trac.webkit.org/wiki/CoordinatedGraphicsSystem
I found that applying the -webkit-backface-visibility: hidden;
to the translating element and -webkit-transform: translate3d(0, 0, 0);
to all its children, the flicker then disappears.
Please refer Prevent flicker on webkit-transition of webkit-transform.
If the fonts are flickering use the following CSS:
html,body {
-webkit-font-smoothing: antialiased;
}
I noticed that after applying CSS3 transforms elements in Chrome looks a bit "crispy" and text unaligned. Solutions in Mathias answer have no effect on this. But here is strange thing - after I've applied webkit filters (i.e. -webkit-filter: opacity(0.99999);
), elements rendered properly and letters in text are aligned. But after that those elements looks blured a bit. Maybe this have effect on your flickering.
First of all, thanks to the great solutions offered here. I always thought in the past there must be something wrong with my code. It wasn’t. I also reasoned out the 2000px border for animations not running smoothly any longer.
Thanks to you guys I now add
/*keep animation smooth in Safari above 2000px*/
@media ( min-width: 2000px ) {
.boxContent {
-webkit-backface-visibility: hidden;
}
}
I did this conditionally because, in fact, pictures don’t render antialiased after adding the class.
At another place I did
/*keep animation smooth in Safari above 2000px*/
.twothousand {
-webkit-backface-visibility: hidden;
}
and added and removed the additional class via JQuery. So the transitions are smooth and render after finished (removing the class again)
A little complicated but it worked fine for me and finally makes animations in Safari above 2000px smooth. Great job, guys!!
An easy solution that solved all my problems was this:
.app * {
transform-style: preserve-3d;
}