WebKit: Blurry text with css scale + translate3d - css

I'm seeing an issue where Chrome and other WebKit browsers massively blur any css-scaled content that also has translate3d applied.
Here's a JS Fiddle: http://jsfiddle.net/5f6Wg/. (View in Chrome.)
.test {
-webkit-transform: translate3d(0px, 100px, 0px);
}
.testInner
{
/*-webkit-transform: scale(1.2);*/
-webkit-transform: scale3d(1.2, 1.2, 1);
text-align: center;
}
<div class="test">
<div class="testInner">
This is blurry in Chrome/WebKit when translate3d and scale or scale3d are applied.
</div>
</div>
Are there any known workarounds for this? I get that in the simple example above, I could simply use translate rather than translate3d - the point here is to strip the code down to the bare essentials.

Webkit treats 3d transformed elements as textures instead of vectors in order to provide hardware 3d acceleration. The only solution to this would be to increase the size of the text and downscaling the element, in essence creating a higher res texture.
See here:
http://jsfiddle.net/SfKKv/
Note that antialiasing is still underpar (stems are lost) so I'm beefing up the text with a bit of text shadow.

I found that using:
-webkit-perspective: 1000;
on the container of your font or icon set kept things crisp for me after experiment with the issue on Android nexus 4.2 for sometime.

A css filter effect is a graphical operation that allows to manipulate the appearance of any HTML element. Since Chromium 19 these filters are GPU accelerates to make them super fast.
CSS3 introduces a bunch of standard filter effects, one of them is the blur fitler:
-webkit-filter: blur(radius);
The ‘radius’ parameter affects how many pixels on the screen blend into each other, so a larger value will create more blur. Zero of course leaves the image unchanged.
Set the radius to 0 will force browser to use GPU calculation and force it to keep your html element unchanged. It's like applying an "hard edges" effects.
So the best solution for me in order to fix this blurry effect was to add this simple line of code:
-webkit-filter: blur(0);
There is also a known bug that only affects retina screens. (See here: Why doesn't blur(0) remove all text blur in Webkit/Chrome on retina screens?). So in order to make it works also for retina, I recommend to add this second line:
-webkit-transform: translateZ(0);

Try this
...{
zoom:2;
-webkit-transform: scale(0.5);
transform: scale(0.5);
}
Or for a more exact approach you can call a javascript function to recalculate the transformation matrix by removing the decimal values of the matrix. see: https://stackoverflow.com/a/42256897/1834212

I came across this issue when using the isotope plugin (http://isotope.metafizzy.co/index.html) in combination with the zoom plugin (http://janne.aukia.com/zoomooz/). I built a jquery plugin to handle my case. I threw it up in a github repo in case anybody could benefit from it. - https://github.com/charleshimmer/jquery-hirestext.

I used javascript to move the text 1px top and then with 100ms after, back 1px down. It's almost unperceptive and solved the problem completely cross-browser.

body {
-webkit-font-smoothing: subpixel-antialiased;
}
or I think you could put that on a specific element, but I was having problems with one element affecting the whole site.
I think it is a problem with custom font-face fonts.

Webkit treats 3d transformed elements as textures instead of vectors
in order to provide hardware 3d acceleration.
This has nothing to do with it. You'll notice that your aliasing problem can be fixed with the addition of duration and direction information (e.g. 0.3 linear). Your having a mare trying to render everything at runtime:
Same for the above ^

Related

css translateZ makes elements blurry

Here's a reproduction of my issue (codepen because apparently stackoverflow's iframe affects the rendering somehow):
https://codepen.io/Ironimus/pen/GRjxpXZ
When using transform: translateZ and perspective inner elements' edges and text become blurry. It works very differently in different browsers, too. In case it also depends on screen or OS, here are a few screenshots with descriptions:
In Google Chrome transform: scale(2) is fine. Text and inner elements become blurry depending on the width of the element with perspective, and it follows very strange logic, when I set the width to 847px or higher it breaks, lower looks ok:
In Mozilla Firefox text becomes blurry if perspective/translateZ combination is used, inner elements are fine, transform: scale(2) is ok as well. width doesn't seem to affect anything:
In Safari everything is hella blurry whatever I do:
Why is it blurry at all and how do I make it right? Using transform: scale(2) for everything isn't a viable option. Are there maybe some rules I should follow to help browsers render 3D transforms with text right?
Supporting Safari isn't a priority but would still be nice
Have you tried adding a custom -webkit to the browser?
I am probably late with this answer but I recently encountered the same behavior when implementing a parallax design for a website.
This is a problem related to text being rendered as bitmaps in Safari, which are not re-rendered on transform: scale(x); but instead blown up in size.
It is possible to manually trigger a re-render of the text in some cases, however this is very finicky and there's no guaranteed way to make it work.
A more comprehensive answer to this was provided by Jack in this thread:
Transform scale() Safari bug when used on elements with border

Image is blurry when upscaling in Mobile Safari

I'm implementing a Pinch to Zoom gesture in JS/CSS. In order to do so, I'm putting a fairly large image source inside a small sized IMG tag and then apply a CSS scale transform to make it bigger.
Things are working fine however on Mobile Safari the image gets blurry once I start scaling up. It should not be the case as the src for the image is big enough to support this size, but somehow Mobile Safari is displayed it as blurry.
I have debugged the issue quite a bit and found out that the culprit is an unrelated div in my page that is setting translate3d(0,0,0). To my understanding this is a Hack to trigger GPU hardware acceleration. What I believe it is happening is that because of translate3d(0,0,0), hardware acceleration is being applied when rendering the <img/>, and since the <img> is small in size, it is drawn small and the scale is applied afterwards.
To better understand the problem, I have it this code, available in in codepen here
HTML
<div>
<div id="translate3d-div"/>
</div>
<img id="image" src="https://www.trackalytics.com/assets/thumbnails/lipsum.com.jpg"/>
CSS
#translate3d-div {
/* If I remove this, the image is not blurry */
transform: translate3d(0,0,0)
}
#image {
width: 95px;
height:76px;
transform: scale(20);
}
This displays the image blurry on Mobile Safari, but it works fine on Chrome in Android.
Is there a way to fix this other than removing the unrelated translate3d? I don't think I can do that since it might be used by some other feature in the webpage.
This is because how WebKit renders transforms when hardware acceleration is enabled (like in iPhone). It increases performance dramatically but affects antialiasing when you apply a 3DTransform when no real transformation happens.
A hackfix is to set a background for the element.
#translate3d-div {
transform: translate3d(0,0,0);
background: transparent;
}
Source: https://dropshado.ws/post/6142339613/resolving-anti-aliasing-on-webkit
I couldn't find a working hack for this, but the workaround I used was to simply create a bigger HTMLImageElement and scale it down initially. Then scaled up it will not look blurry. This made my code slightly more complicated but it is working fine.

Chrome is now blurring text when using transform translateY with percent

Since a few days, I'm experimenting a pretty big issue when using the very cool technique for vertically centering a div with css3 transform (transform: translateY(-50%); ) described here:
https://davidwalsh.name/css-vertical-center
Indeed, the elements (text or images) included in this div get blurry.
I tried a lot of techniques (transform: translateZ(0); backface-visibility; scale(1); translateX( calc( -50% + 0.5px ) ); filter: blur(0); and so on). But nothing actually works.
The only one that works is to use another technique for vertically centering the div, like display:table-cell.
But, for obvious reasons (like the obligation to add a div container), I'd rather not to do so.
So I have two questions :
first, do you know a technique that works ?
second, is it a new issue with the last (or latest) version(s) of Chrome ?
thanks for your help,
David
PS :
all the old solutions expressed here
Webkit-based blurry/distorted text post-animation via translate3d
don't work
For now, I found only one good solution:
transform: translate(-50%, -50.1%)
0.1% - in general user can't see this
No need to calc value
Hope chrome will fix it - the bug exists since 2014))))

CSS Transform Scale makes text blurry

I have a hover effect that when it is triggered, the box enlarges. Only issue i have is that the text seems to blur during the transition and then goes sharp again when 'transformed'.
Before posting on here i decided to have a research and came across this post which seems to be the issue with mine as well:
How to force re-render after a WebKit 3D transform in Safari
http://duopixel.com/stack/scale.html
I have applied their answer to my build and still the blurred effect happens. I have provided a link below and if anyone could advise me with what i have is possible to resolve that would be great!
eg of transition code:
-moz-transform:scale(1.05,1.05);
http://jsfiddle.net/VcVpM/1/
While it's not equivalent, setting the width, height, left, top, font-size attributes in the :hover works without the blurring on Chrome.
.cta:hover {
width: 500px;
height: 500px;
font-size: 400%;
}
The only other work-around "might" be to use animation #keyframes and set a decent amount of them ~5 or 10, it might force a correction of the blurring between each keyframe.
I found this on CSStricks.com:
It appears if you set your transforms to also use
translate3d( 0, 0, 0)
it can fix it, but it does cause fonts to be a bit blurry on rotate/transform. See here: http://codepen.io/WillsonSmith/pen/4/2
I use Jquery and needed my slider's H3 tags to be fixed. Larger text wasn't blurry for me.
I wrote the line
$("#slider1_container").find("h3").css("-webkit-transform", "translate3d(0,0,0)").css("-webkit-text-stroke", "0.15px");
and that fixed it best for me. I needed the -webkit- in front of my transform. I don't know why, as others said not to use it. I uploaded an image of the way it looked with some different settings.

CSS Filter on Retina Display: Fuzzy Images

When you apply a -webkit-filter and a -webkit-transition to an Image and change the filter on hover, the image transition does well, but then the image gets really fuzzy.
Note: This only happens on Retina-Displays — no problem at all with 'normal' ppi-displays, but fuzzy on for example a new MacBook Pro with Retina Display.
My CSS (without vendor-prefixes):
img {filter:grayscale(1);filter:saturate(0%);transition:2s ease;width:200px;height:200px}
img:hover {filter:grayscale(0)}​
Note: to see the effect/bug, I've set the transition-duration to 2 Seconds
Check out my Demo: http://jsfiddle.net/dya2t/7/
How can I fix this?
EDIT: If I set the :hover-state to filter:none its sharp! :-) BUT of course the transition does not work anymore :-/
As soon as there is a filter on an image (even if the value is 0 or 0%), the image gets fuzzy on retina displays (with or without transitions … its just blurry, all the time). I guess this is a Filter-Bug.
This is a known Bug in WebKit https://bugs.webkit.org/show_bug.cgi?id=93471
I managed to get around this issue by applying to the img tag:
-webkit-transform: translateZ(0);
http://jsfiddle.net/78qbn/3/
Child elements with -webkit-backface-visibility: hidden; will resolve this.
http://codepen.io/amboy00/pen/Bxbrd
Joined stackoverflow to let others know since I had to find this out myself:
this bug also manifests (but differently) when trying to print images in chrome. They turn super pixelated!
If you throw a -webkit-filter onto a PNG in chrome regardless of printer or print settings, it prints the image/s at the right size, but downsampled to under 70 dpi. It's visible in the print preview too.
-webkit-transform: translateZ(0); fixed it.
Meatspace repro: prints of same stack of PNGs with & without fix

Resources