42

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.

Brandon Durham
  • 7,096
  • 13
  • 64
  • 101
  • Keep in mind that the flickering can also be caused by turning the GPU rendering on/off. Eg: You have applied the transformation only for the `:hover` selector. – LeZuse Apr 02 '13 at 11:41
  • I think Safari is not the best browser you can get. I don't know about it on OSX, but only Windows. – yunzen Apr 05 '13 at 08:10
  • Try using a background-color directly on the flickering element – yunzen Apr 05 '13 at 08:13
  • 1
    Can you post the example of your animation, so we dont have to write one ourselves and to reduce variables? – yunzen Apr 05 '13 at 08:13
  • What OS do you use Safari on? – yunzen Apr 05 '13 at 13:19
  • I've made a fiddle http://jsfiddle.net/gZ6m8/ Could you test, if it flickers? If not, make some changes so it flickers, so we all get an idea. – yunzen Apr 05 '13 at 13:38
  • @HerrSerker Compatibility-wise and performance-wise Safari is probably one of the best browsers around. You should not just say random stuff. Google didn't embrace WebKit for nothing. It's a solid and strongly abiding engine. Before the uprising of Chrome, Safari had by far the best compatibility/benchmark/performance statistics. It's just personal flavor what makes people say such irrational things. Base your expressions on facts please :) Besides all that, the OP is working with experimental drafts, what can cause (different) problems in each browser, as it's not "done" yet. –  Apr 10 '13 at 16:54
  • Posted a jsFiddle in the original post. – Brandon Durham Apr 11 '13 at 12:12
  • Might be related : http://stackoverflow.com/questions/7908493/considerations-for-css3-transition-performance --> **-webkit-transform-style: preserve-3d;** gave my css3 transition a HUGE performance boost – eivers88 Dec 5 '12 at 23:35 – Milche Patern Apr 11 '13 at 12:59
  • Can I ask why I didnt get the bounty? – Spoeken Apr 12 '13 at 11:34
  • You should have… I accepted your answer. – Brandon Durham Apr 12 '13 at 13:11
  • Looks like it got accepted too late. Well, it ain't that important :) – Spoeken Apr 15 '13 at 09:16
  • @Mathias Madsen Stav - CRAP! Wasn't even aware I missed the deadline. Know if I can start another bounty and award you the points straight away? – Brandon Durham Apr 22 '13 at 14:53
  • No worries man! Btw, you know that by putting preserve-3d on body on that fiddle will fix that problem right? http://jsfiddle.net/ujPMK/2/ – Spoeken May 16 '13 at 09:22
  • 1
    Well, it doesn't necessarily fix it. It makes the entire page blink instead. :) It also grayscales all text on the page, which is an undesired effect. – Brandon Durham May 17 '13 at 14:19

8 Answers8

68

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

Spoeken
  • 2,549
  • 2
  • 28
  • 40
  • Is this related on how I can't create a very big canvas elements (9000x9000 pixels) on the iPad3? I haven't tested on other iPad versions – Hoffmann Apr 10 '13 at 20:03
  • I believe so. But you can create multiple canvases instead. – Spoeken Apr 11 '13 at 08:54
  • I actually tried that, if the sum of all the canvas areas are bigger than 9000x9000 pixels it still doesn't render. When I first found out about this I thought that I was reaching the limit of iPad3 video memory. Worth of note that this also happened on Chrome on my notebook, but the limit was higher (16kx16k I believe). – Hoffmann Apr 11 '13 at 13:49
  • 1
    You should post a new question for this with some code. For all I know you can have a media query with display: none; on canvas - not saying thats the case tho :) – Spoeken Apr 11 '13 at 14:12
  • This did the trick for me :-) body { -webkit-backface-visibility: hidden; } – Malte Schulze-Boeing Jul 23 '13 at 09:47
  • 1
    In my case adding -webkit-transform:translateZ(0) to the flickering items did the job. To my surprize I only had to assign the fix to p and a elements on my site. – Hooman Askari Dec 24 '14 at 22:36
  • That feature flag for Safari to show compositing layers is huge. Very helpful. – rkd Apr 10 '18 at 19:56
  • Wow. Thanks, I would never guess that an element size would cause problems. Changing to multiple elements fixed everything. :) – Raphael Aleixo Feb 21 '20 at 15:26
41

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.

Community
  • 1
  • 1
Rupam Datta
  • 1,849
  • 1
  • 21
  • 36
  • 1
    I'm not sure why you had downvotes, but applying this (with the added "-webkit" prefix) on the children fixed the flicker on Safari 5.1 for me. So here's an upvote. :) – wavetree May 30 '13 at 15:23
  • @gnclmorais Thanks for the edit but should I ask you what is the change you made? – Rupam Datta Feb 26 '14 at 08:47
  • 1
    Nothing crucial, just put the CSS rules in `code blocks`. I'm a little OCD about it. By the way, your answer helped me, it removed the flicker from my headers! I just needed the `-webkit-backface-visibility`. So thank you. :) – gnclmorais Feb 26 '14 at 08:49
  • 1
    This is a good answer as on safari, translate3d() uses hardware acceleration, as opposed to translateY(), translateX(). – Bojana Šekeljić May 11 '15 at 11:51
9

If the fonts are flickering use the following CSS:

html,body {
    -webkit-font-smoothing: antialiased;    
}
Dimitar Tachev
  • 575
  • 4
  • 14
Eugenio Enko
  • 161
  • 1
  • 3
  • 2
    The OP said they were already using this property. Anyway, you could improve your answer by adding documentation resources and explanation how this would help. – dakab Nov 18 '15 at 22:22
4

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.

Miljan Puzović
  • 5,840
  • 1
  • 24
  • 30
  • I think the opacity trigger `-webkit-font-smooting` http://stackoverflow.com/questions/6846953/wonky-text-anti-aliasing-when-rotating-with-webkit-transform-in-chrome/7496660#7496660 – yunzen Apr 05 '13 at 08:11
  • @HerrSerker, opacity is just example. Same happens with ALL webkit filters. Also, direct using of `-webkit-font-smooting` don't work in my case. I can't notice any difference. – Miljan Puzović Apr 05 '13 at 11:47
0

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!!

Garavani
  • 755
  • 1
  • 13
  • 28
0

I too had same problem. mat-icon starts flickering when I open my angular application in Safari browser. It is working fine in Chrome browser. After going through all the options, answered above, my issue could not get resolved. So finally, I set the transition property of my fab-button to none. It resolved the issue.

akgupta
  • 101
  • 1
  • 6
0

I encountered the same issue: when an element transforms with a transition, other unrelated elements would flicker.

will-change helps me solve this problem.

my-element {
    will-change: transform;
}
Jay Wang
  • 2,650
  • 4
  • 25
  • 51
  • Downvote, cause your answer is not clear at all. What is `my-element` ? An wrapper, an item in an wrapper, or what ? Explain a little bit... – Andrei Dec 15 '22 at 22:13
-1

An easy solution that solved all my problems was this:

.app * {
  transform-style: preserve-3d;
}
Chet
  • 18,421
  • 15
  • 69
  • 113
  • Wildcard CSS selectors aren't great for performance, the more elements you add to page the more matches and css updates occur – rkd Apr 10 '18 at 19:55
  • I get that... but it works. Not sure why people are down-voting. Its running in a very performant web application... – Chet Apr 10 '18 at 23:19
  • It definitely works, but it's like burning a forest to remove a single tree. I don't doubt it works fine in some cases/may not always cause problems, but don't think its a very tactical approach – rkd May 10 '18 at 20:20
  • Yeah, I actually removed this code and drastically improved the performance on Android haha. Not seeing the flicker anymore either so its a win win! – Chet May 10 '18 at 21:15
  • +1 because using the wildcard helped me find the element that needed the rule. Then removed the wildcard and specifically targeted the element. – cuka Jul 20 '20 at 18:18