How to prevent Webkit text rendering change during CSS transition
I'm using CSS transitions to transition between CSS transformed states (basically transitioning the scale of an element). I notice that when the element is transitioning, the rest of the text on the page (in Webkit) tends to slightly alter its rendering until the transition is done.
Fiddle: http://jsfiddle.net/russelluresti/UeNFK/
I also noticed that this does not occur on my headers, which have the -webkit-font-smoothing: antialiased
property/value pair on them. So, I'm wondering, is there any way to have the text maintain its default look (the "auto" value for font-smoothing) and not alter rendering during a transition.
I've tried explicitly setting the text to use the "auto" value, but that doesn't do anything. I should also note that setting font-smoothing to "none" also prevents the rendering blink during transition.
Any help is appreciated.
Edit 1
I should note that I am on OS X. While looking at my test in Chrome on Parallels, I did not see the two different paragraphs behaving differently, so this may be an issue exclusive to Macs.
Solution 1:
I think I found A solution:
-webkit-transform: translateZ(0px);
Forcing hardware acceleration on the parent element seems to solve the problem...
EDIT As commented, this hack disables font-smoothing and can degrade text rendering depending on your fonts, browser and OS!
Solution 2:
UPDATE August 2020
You no longer need to target Safari with a media query to enable subpixel font smoothing. The default is fine.
However, although it uses subpixel font smoothing by default, there's a significant fly in the ointment in Chrome's font smoothing, for anyone looking for a consistent rendering of text.
- This is Chrome's rendering of light text on a dark background
- This is Chrome's rendering of dark text on a light background
Look at the size of the whole in the letter e above. The Light text on a dark background is rendered with a perceptibly heavier weight than the dark text on a light background (with identical css font styling).
One solution, for sites respecting the user's dark / light theme setting, is to target Chrome with a media query that is limited to dark mode and switch it to non subpixel smoothing like so:
@media screen
and (-webkit-min-device-pixel-ratio: 0)
and (min-resolution: 0.001dpcm)
and (prefers-color-scheme: dark) {
body {
-webkit-font-smoothing: antialiased;
}
}
The result :
A far more consistent text weight regardless of whether rendering light on dark or dark on light.
Check out the side-by-side comparison of before & after:
--
UPDATE May 2018
-webkit-font-smoothing: subpixel-antialiased
now has no effect in Chrome but in Safari it still improves things a great deal BUT ONLY ON RETINA. Without it in Safari on retina screens text is thin and insipid, whereas with it, text has the proper weight. But if you use this on non retina displays in Safari, (especially at light weight values) text is a disaster. Strongly recommend using a media-query :
@media screen and (-webkit-min-device-pixel-ratio: 2) {
body {
-webkit-font-smoothing: subpixel-antialiased;
}
}
Explicitly setting -webkit-font-smoothing: subpixel-antialiased
is the best current solution if you wish to at least partially avoid the thinner antialiased text.
--tl;dr--
With both Safari and Chrome where the default font rendering uses subpixel-antialiasing, any CSS that forces GPU based rendering, like the suggestions above to use a transform using translateZ or even just a scale transition, will cause Safari and Chrome to automatically "give up" on subpixel-antialiased font smoothing and instead switch to just antialiased text, which looks a lot lighter and thinner, especially on Safari.
Other responses have focused on maintaining a constant rendering by simply setting or forcing font-smoothing to the thinner antiailiased text. To my eye using translateZ or backface hidden significantly degrades the quality of the text rendering and the best solution if you want the text to just stay consistent and you're OK with the thinner text is just to use -webkit-font-smoothing: antialiased
. However, explicitly setting -webkit-font-smoothing: subpixel-antialiased
does actually have some effect - the text does still change slightly and is just about visibly thinner during transitions rendered on the GPU but not as thin as it goes without this setting. So it looks like this at least partially prevents the switch to straight antiailiased text.
Solution 3:
I've noticed that pretty much every time I'm having graphics issues (flickering/stuttering/choppiness/etc) due to a transition, using -webkit-backface-visibility: hidden; on the elements that are acting up tends to solve the problem.