Chrome Incorrectly Rendering Pixels as Fractions

Is there any way to force Chrome to render fractional pixel font sizes accurately?

The only workaround that occurs to me would involve applying -webkit-transform: scale(x), example:

div[style*="10."]  {-webkit-transform-origin: 0 50%;}
div[style*="10.1"] { -webkit-transform: scale(1.01);}
div[style*="10.2"] { -webkit-transform: scale(1.02);}
div[style*="10.3"] { -webkit-transform: scale(1.03);}
div[style*="10.4"] { -webkit-transform: scale(1.04);}
div[style*="10.5"] { -webkit-transform: scale(1.05);}
div[style*="10.6"] { -webkit-transform: scale(0.96);}
div[style*="10.7"] { -webkit-transform: scale(0.97);}
div[style*="10.8"] { -webkit-transform: scale(0.98);}
div[style*="10.9"] { -webkit-transform: scale(0.99);}

The problem, I guess, is that since you are auto-fitting text you are probably getting element.offsetWidth which will give you the width before the scaling. To get it after being scaled use element.getBoundingClientRect().width (your library might already take care of this). You can see this in action here:

http://jsfiddle.net/Cfd5a/

Can a CSS pixel be a fraction?

Yes, you can specify fractional pixels. As this has been part of CSS since the very first version, it should be well supported by any browser that supports CSS at all.

Reference: CSS 2.1: 4.3.2 Lengths

"The format of a length value (denoted by <length> in this
specification) is a <number> (with or without a decimal point)
immediately followed by a unit identifier (e.g., px, em, etc.)."

When the elements are displayed on the screen, most browsers will naturally round the position to the nearest pixel when using 100% zoom level. On higher zoom levels you will notice that fractional pixel values are recognized.

Sub-Pixels calculated and rendered differently among browsers

As you already know, the problem arises from a different approach to subpixel calculus between browsers

In Chrome, for instance, borders can have a fractional size, but margins are handled different (as integers).

I don't have documentation about it from the Chrome team, but it's what can be seen in dev tools:

dev tools capture

AFAIK, there is not a way to change that.

Instead, you can transfer the use of the margin in the button to a border.

Since you need to get space for the 1px border of the input, do the same in the button, set a 1px border (instead of a margin), and set it transparent.

The remaining trick is to set the background-clip property to padding box, so that this transparency is not affected by the background

There is another bug in Chrome, the padding expressed in em is not reliable at this level of precision when the browser is zoomed. I changed this in the snippet.

Since we are using the border button to get the dimension ok, we can style the border using instead a inset shadow.

* {  margin: 0; padding: 0; box-sizing: border-box;}button, input, wrapper {  display: inline-block; border-radius: 3px;}
.wrapper { position: relative; width: 60%; margin: 1em; background-color: #ccc;}
input { border: 1px solid red; width: 100%; background-color: limegreen; line-height: 3em;/* padding: 0.75em; */ padding: 10px;}
button { position: absolute; right: 0; top: 0; bottom: 0; border: 1px solid transparent; width: 7em; margin: 0px; background-clip: padding-box; box-shadow: inset 0px 0px 0px 2px black;}
<div class="wrapper">  <input type="text">  <button>Test</button></div>

Force Chrome to use subpixel rendering for floats

Browsers round fractional pixels automatically and this is browser specific, some round it up, some down; There is no way to force it to do one or the other with CSS.

A solution could be to work with LESS, there are functions for that (ceil, floor).

But if you need a solution with CSS I would just suggest define the width as calc(100% - 0.5px) / calc(100% -1px) or 99.9%. That's just not perfect, but a solution. You can adjust it as you like and as it works for you.

But I'm not sure your problem comes from that.
Take a look at the following fiddle and tell me if it solves your problem. Instead of floating I use a layout based on display:inline-block here, and it seems like there is not such a problem.
https://jsfiddle.net/a693yj52/

Is there such a thing as fractional pixel?

There is no such thing as fractional pixel. Pixel is the smallest screen unit.

The thing you're experiencing happens because of the browsers math engines. Some of them round the decimal pixel part up to the next integer, and some of them floor it down.

To avoid that just define your pixels without decimal points. If you want to make the 2 elements visually closer you can play around with colors, for example - if you give a darker border to some elements they will seem to be closer - http://jsfiddle.net/fDbUj/



Related Topics



Leave a reply



Submit