Font looks blurry after translate in Chrome
Asked Answered
D

11

37

EDIT 2016-07-04(Since this question is getting popular): This is a bug in Chrome. Developers are actively working on a fix.

EDIT 2017-05-14 The bug seems to be fixed, the fix will be introduced in Chrome 60

EDIT 2018-05-04 A fix has been merged, but the bug still appears to be present.

So I have this very ugly-looking window that is centered on the screen by this CSS:

.popup
{
   position: fixed;
   top: 0;
   bottom: 0;

   transform: translate(-50%, -50%);
}

However, it looks like this on Chrome (the font looks really blurry):

Chrome

But like this on Firefox:

enter image description here

When I remove the transform rule, the text looks nice and crispy again, but then it's no longer correctly centered.

When I go to chrome://flags and execute #disable-direct-write it looks nicer, but users are obviously not going to do that and it doesn't solve the problem.

How can I make my font look nice while still having the window centered?

My chrome version is 44.0.2403.155

I have a three.js demo using WebGL that renders on a background canvas. When I disable the demo, the problem no longer occurs.

JSFiddle with the background.

JSFiddle without the background.

Davon answered 16/8, 2015 at 11:29 Comment(13)
subpixel rendering..... can you have a defined width for .popup?Kidding
@DanielA.White I do not have a defined width for .popup.Davon
can you? if you do, then you can center it a different way.Kidding
@DanielA.White I could probably do that, but I prefer not to. You mean setting the width to x pixels and then do a margin-left of -x pixels?Davon
I am using chrome version 45.0.2454.37, And it seems the problem is resolved, jsfiddle.net/5Lgsmjw9Aphrodite
@LaxmikantDange Which means the problem will eventually solve itself?Davon
@Davon did you try to add transform: translateZ(0) (in your case it'd be transform: translate3d(-50%, -50%, 0)?Gauleiter
@SergeyDenisov I tried that too, but that had no effect.Davon
@Davon could you add the working code snippet on jsfiddle.net or here?Gauleiter
@SergeyDenisov jsfiddle.net/xa0o9s6y This is odd. The problem doesn't seem to occur in this demo.Davon
@SergeyDenisov I updated the problem, it's something with the background thinggie I'm makingDavon
@Davon yes, it's OK in the JSFiddle in Chrome 44 on Windows 7/8.1/OS X. You should add your background in the JSFiddle.Gauleiter
Let us continue this discussion in chat.Gauleiter
U
16

A suggestion from a related discussion solved the issue for me: https://mcmap.net/q/426816/-css-translate-with-percentage-causes-blurred-image

Using calc with some offset solved the issue in my case:

transform: translate(calc(-50% + 0.5px), calc(-50% + 0.5px));
Unclothe answered 18/5, 2018 at 13:6 Comment(0)
R
10

I've tried different solutions in different, sometimes scary, combinations:

  • translate3d instead of translateY
  • zoom:2; transform: scale(0.5); or zoom:0.5; transform: scale(2);
  • transform: translate(calc(-50% + 0.5px), calc(-50% + 0.5px));
  • -webkit-filter: blur(0);
  • perspective: 1000px
  • scale(1.0, 1.0)
  • -webkit-font-smoothing: subpixel-antialiased;

none of them work in july 2019.

The only solution i found for modals, that should be centered - to use a flexbox aligment instead of transform: translate.

.modal__container {
  display: flex;
  justify-content: center;
  align-items: center;
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background: rgba(0, 0, 0, 0.5);
}

  .modal {
    box-sizing: border-box;
    max-width: 80%;
    max-height: 80%;
    padding: 20px;
    overflow-y: auto;
    background: #fff;
  }
<div class="modal__container">
  <div class="modal">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </div>
</div>
Randolphrandom answered 18/7, 2019 at 18:32 Comment(2)
flexbox it's ideal with one modal/popup, when you need multiple in different positions you are in troubleEsdraelon
Yes, every modal needs it's own container in situation with multiple modals on different positions.Delmerdelmor
L
5

Problem in half of pixel.

Try: transform: translate(-50%, -51%);

It will work!

Lethe answered 10/8, 2016 at 13:42 Comment(2)
No, it does not work. it might look nicer at a specific situation and specific resolution, but this is not a solution to the problem.Davon
Give me example when it's not working. This problem exist only in Chrome. I saw many solutions like translateZ(0) or perspective:1000px or z-index:1. Idea to move your layout to another layer. But problem in many cases when you are using scale(1.1) or translateX(-50%) not enough: 0.5px and browser making text like blurry. In many cases you can change height of current tag (Add 1px).Lethe
G
3

I found out -webkit-filter: blur(0) could fix your blurry font in Chrome on Windows:

JSFiddle

#projectPopup {
    ...
    -webkit-filter: blur(0);
    -webkit-transform: translate(-50%, -50%);
    transform: translate(-50%, -50%);
}
Gauleiter answered 18/8, 2015 at 9:54 Comment(2)
@Davon oh, it's strange(. It's OK in my Chrome 44 on Windows 7/8.1/10, OS X, Ubuntu 14.04, something like this. Which OS do you use? Is this snippet crashed too?Gauleiter
It's probably because I'm using Chrome 45 now. I'll test it on Linux with the latest stable version(44), I'm sure that will be fine.Davon
R
1

Use a normalization of the transform after your animation:

Transform X/Y normalization

Or We scale the texture with zoom double, then scale down again. In some cases this cannot be applied due to other complex transformations or translations, and is not perfect.

...{
zoom:2;
-webkit-transform: scale(0.5);
transform: scale(0.5);
}
Repudiation answered 9/3, 2016 at 13:24 Comment(2)
zoom: 1.05; help for meUganda
scale and translate do not really mix. This ended up moving my text down too much.Nsf
H
1

The height of the elements must be even numbers https://prnt.sc/mtxxa2

Handal answered 6/3, 2019 at 8:43 Comment(0)
D
1

2019-04-15, still happening to me in Chrome. Found that changing position: fixed to absolute fixed it:

.popup
{
   position: absolute;  <-- just like that
   top: 50%;
   left: 50%;

   transform: translate(-50%, -50%);
}

Using absolute may or may not suit your particular case, just my 2 cents.

Dekeles answered 15/4, 2019 at 15:42 Comment(0)
J
1

The only solution that worked for me:

Translates can cause blur due to result not being rounded to the nearest pixels, so rounding the div height to an even number fixes it.

We can't do it in CSS as it doesn't know yet its final height, so we have to do it after rendering. Using Jquery is a breeze:

$(window).on("load", function() {
    if($('.popup').height()%2==1) $('.popup').height( 2*Math.round($('.popup').height()/2 ) ) ;
    if($('.popup').width()%2==1) $('.popup').width( 2*Math.round($('.popup').width()/2 ) ) ;
});

Credits: https://mcmap.net/q/426817/-round-div-height-to-the-nearest-even-number-if-it-has-an-odd-value

Joh answered 7/9, 2020 at 8:31 Comment(0)
V
0

First of all add overflow: hiddden to the parent element of the modal, if that's not enough add this to modal's style : display: contents Happy coding, love from Mauritania

Variegated answered 27/6, 2020 at 19:51 Comment(0)
M
0

I don't have a pure CSS solution but in my case I was able to resolve this issue by forcing "pixel-perfect" alignment. I'm suspecting that Chromimum based browsers don't handle CSS transforms as elegantly as Firefox. Below is my solution:

/**
 * Gets the nearest CSS pixel position that aligns with a device pixel.
 * @param {{x: number, y: number}} position Element position in CSS pixels.
 * @returns {{x: number, y: number}} An object containing the "pixel-perfect" x and y position.
 */
function roundToNearestPhysicalPixel(position) {
  // Reference: https://web.dev/articles/device-pixel-content-box
  // Device pixel ratio: number of physical pixels needed to form a single CSS pixel.
  const fracPixels = devicePixelRatio % 1;
  const cssPixelRoundingIncrement = 1 / fracPixels;
  const inc = cssPixelRoundingIncrement;
  return {x: Math.round(position.x / inc) * inc, y: Math.round(position.y / inc) * inc};
}

In my case, I was transforming an element to match the user's mouse position using JavaScript. I know this won't help most people but I think it explains the symptoms - essentially we are observing an issue with "pixel snapping".

Manasseh answered 13/6 at 21:0 Comment(0)
I
-1

I tried every solution and only this is working for me (chrome 53)

dialog {
  position: fixed;
  top: 50%;
  transform: translate(0, -50%);
}
Instable answered 28/9, 2016 at 19:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.