New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 521364: Transformed text at fractional offsets is very blurry.

Reported by, Aug 16 2015

Issue description

UserAgent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.37 Safari/537.36

Example URL:

Steps to reproduce the problem:
1. Create a new webpage
2. Create a new element with WebGL rendering on the page
3. Create a element with text with the following CSS rules:

position: fixed; /* or absolute */
top: 50%; /* or anything else */
left: 50%; /* ^ */
transform: translate(-50%, -50%); /* or any other inner value */

What is the expected behavior?
The font of the element with the rule "transform: translate(-50%, -50%);" will blur

What went wrong?
The font blurs but it should be crisp sharp like the rest.

Does it occur on multiple sites: Yes

Is it a problem with a plugin? No 

Did this work before? N/A 

Does this work in other browsers? Yes 

Chrome version: 45.0.2454.37  Channel: beta
OS Version: 6.1 (Windows 7, Windows Server 2008 R2)
Flash Version: Shockwave Flash 18.0 r0

Platforms affected: Windows & Linux, not sure about OS X but report says not so.

Link to the same demo without the WebGL element(for comparison):

This is also the case on Chrome 44.0.*

Comment 1 by, Aug 17 2015

Labels: -Cr-Blink Cr-Blink-WebGL Cr-Blink-Compositing

Comment 2 by, Aug 17 2015

Labels: -Type-Bug -OS-Windows Type-Bug-Regression OS-All M-46
Status: Assigned
Able to reproduce the issue on Windows, MAC and Linux. This is a regression issue broken in M36 and below is the bisect info:



From Blink roll, suspecting - 170527

Comment 3 by, Aug 17 2015

Status: Untriaged
Reproducible on 46.0.2478.0 (Official Build) dev (64-bit) on Linux with NVIDIA GPU. It looks like the translated element isn't pixel aligned. Resizing the window changes how the blurred text appears. I assume the presence of the WebGL-rendered canvas promotes the div into a separate layer and that's the essential difference between the two examples?

Comment 4 by, Aug 17 2015


Comment 5 by, Nov 3 2015

I can't reproduce this yet on 48.0.2547.0.

Comment 6 by, Nov 3 2015

Status: WontFix
I can now reproduce. This is unfortunately a fundamental limitation of compositing.
The text ends up in a composited layer because it overlaps composited
content (WebGL in this case).

If you position a composited layer at a fractional offset, the text will look blurry, because it has to be drawn at a fixed offset from the composited layer. There seems to be no way around this; snapping composited layers or contents within them will have other indesireable side-effects.

The text composited layer is at a fractional offset because of the % translation. A simple fix for this page could be to use an exact pixel offset instead.

Comment 7 by, Nov 3 2015

 Issue 123306  has been merged into this issue.

Comment 8 by, Nov 3 2015

Summary: Composited text at fractional pixel offsets has blurry rasterization. (was: Font blurs when using translate on a webpage with a WebGL Canvas)

Comment 9 by, Nov 3 2015

Status: Assigned
Thought some more about this bug along with enne@. I think we can do better in some of these cases, especially ones where the page has not specified any fractional positions explicitly.

Comment 10 by, Nov 3 2015

Summary: Transformed text at fractional offsets is very blurry. (was: Composited text at fractional pixel offsets has blurry rasterization.)
The root issue is that that fractional transforms lead to very blurry text rendering when composited.

(Non-transform positioning sometimes leads to very slightly bad text, but it appears to actually be absence of LCD text.)

Example 1:

<!doctype HTML>
<div id="projectPopup" style="transform: translate3d(0.5px, 1px, 0px);">
    Blurry text

Example 2:

<!doctype HTML>
<div id="projectPopup" style="transform: translate(0.5px, 1px); will-change: transform">
    Blurry text

Example 3:

<!doctype HTML>
<div style="width: 100px; height: 100px; will-change: transform;"></div>

<div id="projectPopup" style="position: absolute; top: 10px; left: 10px; transform: translate(0.5px, 1px); ">
    Blurry text

Removing compositing triggers from the above examples lead to non-blurry text. Example:

<!doctype HTML>
<div style="width: 100px; height: 100px;"></div>

<div id="projectPopup" style="position: absolute; top: 10px; left: 10px; transform: translate(0.5px, 1px); ">
    Blurry text

Comment 11 by, Nov 3 2015

Example 1 is I think a lost cause. But for examples 2 and 3, we could avoid representing 2D transforms as composited layer transforms, and instead draw them in software.

Comment 12 by, Nov 6 2015

 Issue 550346  has been merged into this issue.

Comment 13 by, Nov 6 2015

 Issue 130940  has been merged into this issue.

Comment 14 by, Nov 6 2015

Additional notes

1. Safari has the same behavior.
2. Firefox does not. It instead appears to snap the content to the nearest pixel, and
paints everything crisply.
3. What I suggested in comment 11 can only be done if there are no composited descendants.

(#2 might have undesirable side-effects if you try to put two transformed layers right next to each other and don't want seams.)

Comment 15 by, Nov 9 2015

 Issue 166812  has been merged into this issue.

Comment 16 by, Nov 13 2015

Update based on more research:

I reminded myself that composited layers are positioned at pixel-snapped locations for precisely this
reason. Content is then painted within that pixel-snaped composited layer with fractional offsets
that are accumulated from the root of the page.

Unfortunately, the existing code does not take into account transform, because in general transforms
are not simply offsets. Fixing this bug could involve incorporating transform in cases when it is in
fact a simple offset, and there is no direct compositing reason.

Comment 17 by, Nov 17 2015

 Issue 477271  has been merged into this issue.

Comment 18 by, Nov 19 2015

 Issue 506621  has been merged into this issue.

Comment 19 by, Jan 22 2016

 Issue 119470  has been merged into this issue.

Comment 20 by, Mar 25 2016

 Issue 406529  has been merged into this issue.

Comment 21 by, Mar 26 2016

Blocking: 596382

Comment 22 by, Apr 1 2016

Prototyped and discussed at length with enne, vmpstr and fmalita. The current plan is to
implement a mode in which:
1. Transform is baked into the DisplayItemList if affine, plus appropriate offset to make its top-left still be between (0,0) and (1, 1)
2. The layer is expanded accordingly to take into account the increased size of the layer (subpixel offset, increased size due to scaling)
3. The layer is marked as non-opaque

This will suffice for the use case of a layer which is composited for indirect reasons, and solve the use cases
mentioned in this bug. It will not directly improve the use case specified in  issue 596382 , except insofar as
some of those use cases result in indirect compositing due to overlap (which may be common).

A later improvement to apply the same approach to directly-composited transforms would be:

4. Only apply (1) if the affine matrix is invertible
5. Plumb the affine matrix plus offset from (1) to LayerImpl
6. When animating the transformation in the impl thread, preconcat the animated transform matrix with inverse of the matrix from (5)

This would allow for good pixel-snappping of text and images for directly-composited layers, but they would still blur during animation of transform, even involving scale change.

If high-quality 2D pixel-snapping is required on every frame, Enne and I concluded that compositing is simply not the right approach, and the developer should use a non-composited 2d matrix transform.

Comment 23 by, Apr 1 2016

A third improvement would be to not bake the affine matrix into the DisplayItemList,
and instead allow the RasterSource to adjust it when changing content scale.

Comment 24 by, Apr 1 2016

Though it seems this third improvement would only be possible if the scale did not change the bounds of the layer.

Comment 25 by, Apr 1 2016

 Issue 483381  has been merged into this issue.

Comment 26 by, Apr 25 2016

Seems like javascript sliders with `transform3d` will turn off subpixel font rendering on the entire site in Chrome:

This needs to be fixed ASAP!
13.8 KB View Download
14.5 KB View Download

Comment 27 by, Apr 25 2016

Issue 600120 has been merged into this issue.

Comment 28 by, May 23 2016

 Issue 612878  has been merged into this issue.

Comment 29 by, May 31 2016

 Issue 616163  has been merged into this issue.

Comment 30 by, May 31 2016

Tien-Ren will pick this up.

Comment 31 by, Jun 1 2016

Hello all!

Is this task only about blurry fonts?

There are a lot of blurry things in HiDpi mode on Windows.
For example:
1) Set 150% dpi
2) Open attached file img_blurry.html
Black rect is blurry.

Do you have any plans to fix all these cases (may be project like Slimming Paint)?
1.4 KB View Download

Comment 32 by, Jun 1 2016

What do you mean by 150% DPI?

Comment 34 by, Jun 1 2016

I see. So it's equivalent to --force-device-scale-factor=1.5 ?

Comment 36 by, Jun 21 2016

Components: -Blink>WebGL Internals>Compositing>Rasterization
Labels: -OS-Windows -Arch-x86_64 OS-All
Status: Started (was: Assigned)
Hey just want to give you guys a quick update. I'm actively working on this issue.

The problem was due to we raster things in an element's local space. If the element has a fractional translation, then the rasterized texture would be pasted onto the screen with the fractional translation using linear resampling, resulting in the blur.

The solution is to raster things in a space that is pixel-aligned to our physical screen. i.e. applying the fractional translation to the vector graphics commands instead of rastered texture.

The fix will be coming in two parts: 

1. The first part that allows our raster system to raster with any general matrix. This part is almost done. I have a WIP but it still has a bug that causes performance regression. I expect to finish it within a few days.

2. The second part that allows our tiling management to be able to manage set of textures that comes with different raster translation. I was originally going for general matrix but turns out the tile coverage computation becomes very difficult. I will instead do a simpler version that only supports translation and scale. I estimate this will need another week of work.

I will try to land this by M53 branch but time is tight. Pretty sure this can be fixed by M54.

Comment 37 by, Jun 22 2016

Souinds great. Thanks for the detailed update!

Comment 38 by, Jun 22 2016

Comment 39 by, Jun 22 2016

Re comment 38: no I don't think so. I think that is solved by issue 485650 (use zoom for device scale). This will allow us to pixel-snap at device pixels in cases when devicePixelRatio is not an integer.

The feature might be far enough along that you can test with the flag on to
verify it fixes your use case. Please try that and let me know.

Comment 40 by, Jun 22 2016

"enable-use-zoom-for-dsf" helps!
Thank you.

Comment 41 by, Jun 22 2016

Labels: -Pri-2 Pri-1
I suggest increasing the priority, as the issue makes reading of any page on high resolution monitors impossible. I have a stable repro on HP Z840 machine, if any of my chromium colleagues are interested in testing.

Comment 42 by, Jun 22 2016

 Issue 587659  has been merged into this issue.

Comment 43 by, Jun 22 2016

Labels: -Pri-1 Pri-2
Boris, I don't think that's this bug.  As trchen@ said, that should be covered by  You can try --enable-use-zoom-for-dsf locally and see if that fixes your problem.

Comment 44 by, Jun 23 2016

@trchen: Thanks a lot for the update on this and the work you are doing!

Just a tiny question, can you check if the Leaflet div demo page is being fixed in your version (it was merged into this issue some time ago):,output


Comment 45 by, Jun 24 2016

#44: I'm sorry the leaflet issue is in fact a different problem. I will re-open issue 600120 and share my analysis.

Comment 46 by, Jun 24 2016


Comment 47 by, Jul 8 2016

I've made 2 examples showing that when there's any element animating, all elements with fractional transforms are blurry.

Example 1 (blurry for 3 seconds):

Example 2 (always blurry):

Example 2 always blurry is too bad, because a small logo rotating forever is definitely a possible use case.

Comment 48 by, Jul 8 2016

Not only text, but images are also blurry if the image has 1px-wide lines. For example:

Hope it will be solved soon.

Comment 49 by, Jul 10 2016

Should I create a new issue for the following, or is this the same issue?

data:text/html,<!DOCTYPE html> <style> @keyframes a { 50% { transform: translateY(10px); } } .c { height: 21px; width: 101px; transform: translate(50%, 50%); } .a { animation: a 1s infinite; } </style> <div class="c"><div class="a">Animated</div>Text</div>

This is as minimal as I managed to create. If you remove any of the CSS rules, it gets a little better, or completely goes away.

Comment 50 by, Jul 11 2016

Hello trchen!

Any update on second part in comment 36?

Comment 51 by, Jul 12 2016

 Issue 626704  has been merged into this issue.

Comment 52 by, Jul 14 2016

 Issue 625114  has been merged into this issue.

Comment 53 by, Jul 20 2016

 Issue 629837  has been merged into this issue.

Comment 54 by, Jul 22 2016


I verified locally this will fix the test case uploaded by OP and #47, #48.
The CL still need some polish (not regressing performance, dedupe code, add tests, and such) but we are confident it will fix many render quality issues.

Comment 55 by, Aug 3 2016

 Issue 629522  has been merged into this issue.

Comment 56 by, Aug 15 2016

Note that in simpler cases, the underline moves (and gets thicker) but the text remains in the same place -
data:text/html,<!doctype html><style>body{transform: translate(0, 0.5px);}</style><div><a href="f">text</a>

Should I file an issue for this, or is this the same issue?

Comment 57 by, Sep 10 2016

I'd like to note one thing about this issue.
I have a <div> with "style='transform: rotate(-90deg)'" on top of the <canvas> with some Kinetic.js code.
And on small font sizes (13 in presented example), there is an obvious difference in blur, depending on the parity of length of the string(!!!). Thus, if length is even there's no severe blur (see Capture1), but if the length is odd the text is blurred (see Capture2)!
What is more, it all depends on the text itself! So, if I just write 11 "g"'s it's blurred (see Capture3), but if they are 11 random letters, it seems OK (see Capture4)! (Though it may seem so because of different shapes of different symbols).
By the way, on larger font sizes (24 in example) there seems to be no effect from both changing length of the text (compare Capture 5 and 6) and changing text itself (compare Capture 5 and 7).

Hope it helps
1.9 KB View Download
1.7 KB View Download
2.1 KB View Download
2.5 KB View Download
3.2 KB View Download
4.0 KB View Download
5.8 KB View Download

Comment 58 by, Oct 6 2016

@trchen - are you still actively working on this?

Comment 59 by, Oct 6 2016

Yes, he is working on it.

Comment 60 by, Nov 18 2016

 Issue 651580  has been merged into this issue.

Comment 61 by, Jan 19 2017

 Issue 578788  has been merged into this issue.

Comment 62 by, Feb 18 2017

Question, can this happen as a result of animations as well? I have checked my CSS and there are no transforms on the affected elements but some users in Chrome are reporting the text as blurry. Any suggestions?

Comment 63 by, Feb 18 2017


Comment 64 by, Feb 18 2017

Re comment 62: could you please post an example URL we can check? Also please specify
the platform and computer hardware you are using.

It should not happen if there are no transforms.

Comment 65 by, Feb 18 2017

#52 - there are multiple types of unintended font blurriness. One can result from sub pixel transforms (this issue) and one can result from being on a hardware accelerated layer (or at least it used to happen on Windows, perhaps it is gone with the switch to DirectWrite, though). Perhaps yours is the latter.

Comment 66 by, Mar 22 2017

What's the current status on this, and what is remaining? Predictability program has set an OKR this quarter to gain traction on the top 50 starred bugs: either by closing them, stating what milestone the fix will ship, or setting a NextAction date so that we know when to check back in.

Comment 67 by, Mar 23 2017

Version 59.0.3043.0 (Official Build) dev (64-bit) Debian Sid

Hello from merged 651580. Whatever the issue I was seeing in that bug seems to have been fixed over the last month or two, that or my eyes have grown old and I just can't tell anymore. I cannot repro what's described in 521364 (this current bug's) description.

Comment 68 by, Mar 23 2017

My duped (651580) repro still blurs text in 56.0.2924.87 (64-bit) and 57.0.2987.110 (64-bit) running both with or without --force-device-scale-factor=1

Comment 69 by, Mar 23 2017

NextAction: 2017-03-27
Sorry for sitting on this for long. I've been actively finishing the patch this week.

Comment 70 by, Apr 3 2017

Project Member
The following revision refers to this bug:

commit f0cb63ee25776d29838be8782ce9adb607010ce8
Author: trchen <>
Date: Mon Apr 03 22:38:17 2017

[1/5] Pass transformed rasterization policy from Blink

This CL adds an "allow transformed rasterization" input flag to cc layers,
and implements a policy in Blink to decide when to enable to flag.

With existing implementation in cc, layers are always rasterized in some
scaled layer space. The idea is that scaled local space may not always align
to target surface pixel-by-pixel. Rasterizing in such space could result in
resampling error at draw time. With this flag enabled, cc would be allowed
to choose arbitrary space to raster the layer for better draw quality.

This CL only enables the flag for layers that are indirectly composited
(e.g. due to children, overlapping, etc...). Such layer by itself would not
be composited, and Skia would have raster it in device pixel space. Therefore
these are good candidates for cc to raster in target space as well.

The flag currently does nothing. The actual transformed rasterization will
be implemented in followup patches.



Cr-Commit-Position: refs/heads/master@{#461561}


Comment 72 by, May 11 2017

Labels: M-60
Note: All 5 parts have been landed. We should start to see subtle quality change on some of the instances in M60.

Comment 73 by, May 11 2017

Mark as fixed then?

Comment 74 by, May 11 2017

Status: Fixed (was: Started)

Comment 75 by, Jun 2 2017

This is fixed? It seems animation still causes blurry text in Chrome Canary. See my demo (if it's not blurry please resize the window):

Comment 76 by, Jun 2 2017

Status: Started (was: Fixed)
Re: #75

Thanks for your feedback! I can repro your case locally, and your case is expected to be covered by the fix.

Luckily I was able to track down the root cause, it was due to inline transforms being considered as a "direct reason" to composite (in which case, the fix doesn't kick in), but it shouldn't be. The case no longer repros when I moved the transform to a stylesheet. Could you confirm that for me? It will help me verify the root cause and make a fix. Thanks!

Comment 77 by, Jun 3 2017

Yes I can confirm that. When I move the transform to a stylesheet it's not blurry.

Comment 78 by, Jun 5 2017

Labels: PaintTeamTriaged-20170605 BugSource-User

Comment 79 by, Jun 14 2017

Project Member
The following revision refers to this bug:

commit bd15a69f51f749184a854ca9ed3694839cf75d70
Author: Tien-Ren Chen <>
Date: Wed Jun 14 23:55:41 2017

[blink] Relax transformed rasterization policy

Transformed rasterization were enabled only for layers that are
composited for overlapping. This CL broadens the criteria to include
every layers that don't have a direct compositing reason.

This will improve draw quality on affected layers, but may also
slightly increase raster costs.


Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2
Change-Id: I1f52ba1b6ca77dea0d60a6adc4483ea255420746
Reviewed-by: Chris harrelson <>
Commit-Queue: Tien-Ren Chen <>
Cr-Commit-Position: refs/heads/master@{#479548}

Comment 80 by, Jun 15 2017

Status: Fixed (was: Started)
From M61 the fix will be applied more aggressively.

Comment 81 by, Aug 14 2017

This issue is still present on chrome 60
( - posted in comment 75)

Comment 82 by, Aug 15 2017

Yes, but as @trchen pointed out, from v61 the bug should disappear.

Comment 83 by, Nov 1 2017

I'm still seeing the original issue from in Chrome Version 62.0.3202.75 (Official Build) (64-bit).

See attached. You'll either see good or bad based on on the window size, such that the percentage based width gives a non-integer transform I think.
11.8 KB View Download
10.5 KB View Download

Comment 84 by, Nov 1 2017

After playing around for a bit with the fiddle in comment 83, it appears the position can be set to any non-integer value and everything is fine, but the moment that transform:translate has any non-integer values the text is blurred.(Looks like this causes a promotion to a layer, even though the non-integer top/left doesn't?)

Comment 85 by, Nov 6 2017

Status: Assigned (was: Fixed)
I think we can make position:fixed an indirect compositing reason. 

Comment 86 by, Feb 1 2018

I am still experiencing this issue on Windows 10 and Chrome 63.

Comment 87 by, Mar 26 2018

Still seeing it under Chrome 65 on linux.

Comment 88 by, Apr 20 2018

Chrome 65 / Linux:

translateX(-50%) on layer promoted element sometimes (50/50) appears blurry. Is this a technical limitation due to pixel fractions or are there any known fixes/workarounds?
15.3 KB View Download
13.0 KB View Download

Comment 89 by, Apr 24 2018

Although 483381 was merged into here it's a good reminder that translating by 50.1% corrects blurry border issues.

Comment 90 by, Jul 2 2018

So this issue is still around since 2014 at least! please do something?

By the way, the blur is cause by subpixel values not being rendered by the display, because its density its not compatible and such thing as half a pixel does not exists?

This effect can be also seen on this issue (when using css animations/transitions like translations 50%)

It's so obvious, try this and see for yourself:,css,js,output

I believe google can do it better, by solving this annoying issue internally? by correcting the transformation matrix automatically (rounding the decimal matrix values to integers) and the blur dissapears! this would solve all those issues? Because the solution os that jsbin requires to apply the same correcting function to the parents in case they use transforms because its not clear which fault is from, the child or the parent being translated... But if the engine could round those values would solve this.

Comment 91 by, Sep 12

This issue is still happening on 69.0.3497.92 Chrome.

The 50.1% solution (#89) does not solve all the problem cos it could still result in a non-integer value.

Best regards to the dev team.

Comment 93 by, Sep 12

Like a charm!
As seen above (#90), your function do the job.
Would be awesome some native solution.

Comment 94 by, Sep 12

I'm leaving the team thus re-assigning bugs.

I think there are still room for improvement in this area. SPv2 rasters most render surfaces in device space by default, and should largely solve instances due to effects. However this is likely to change prior to shipping to match existing behavior/quality/performance characteristics, in order to de-risk SPv2.

What I'm trying to emphasize is that it is easier to experiment and tryout different raster policy in SPv2, simply by generating layers with a different transform node in PaintArtifactCompositor.

For SPv1 I don't know any improvement that can be easily done. :(

Comment 95 by, Sep 28

Labels: Hotlist-Interop
I've tested in Firefox Nightly (Linux) and Edge 17 (Windows) on local hardware to confirm that the text rendering in sharp. I've also tested Safari 11.1 on BrowserStack and I *think* the text is blurry (as in comment #14), but it's hard to say because it could be due to compression by BrowserStack.

Recently I've also been pointed at a few bugs that *could* be because of this, but I haven't minified to confirm:

While this isn't web observable in the typical sense, adding Hotlist-Interop as it is a cross-browser differences that it appears web developers have to adapt to.

Comment 96 by, Sep 28


Comment 97 by, Oct 17


Comment 98 by, Jan 25

Owner: ----
Status: Available (was: Assigned)

Comment 99 by, Feb 4

Similar issue:  Issue 573146 .

I suspect that CSS property `backface-visibility` has something to do with this blurriness.

I sometimes see some comments in Stackoverflow which say applying `backface-visibility: hidden;` makes text blurred or fixed.

Sign in to add a comment