Sub-Pixels Calculated and Rendered Differently Among Browsers

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>

1px calculation issue with browsers (sub-pixel problems)

That's because of Sub-Pixel Problems.

Each image takes 50% of the container. For example, if the container is 100px wide, each image will be 50px wide.

But the width of container could be an odd number of pixels, e.g. 101px. Then there are three reasonable possibilities:

  • Make one image 50px wide and the other 51px. Then the images won't be equally wide, even if you specified the same width to both of them.
  • Make both images 50px wide. Then there will be a 1px gap
  • Make both images 51px wide. Then they won't fit, overflowing the container or wrapping to the next line.

Each choice has its downsides, but nowadays browsers seem to prefer the first option. However, in this case, the images have an intrinsic aspect ratio, so different widths will produce different heights, and then the 1px gap is created horizontally instead of vertically.

It seems Firefox detects than, and thus makes the smaller image as tall as the other one, breaking the aspect ratio. Chrome prefers to enforce the aspect ratio.

There is no way to change this. It's completely implementation dependent:

The especially strange part, in all of this, is that there’s really no
right, or wrong, here. How this behavior is supposed to play out by
the rendering engine isn’t dictated by the CSS specification, having
it be left up to the implementation to render as it sees fit.

Browser rendering differences at pixel level (width, height, ...) of DOM elements

The returned value of ClientRect() is TextRectangle, see here: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIDOMClientRect

All coordinates are relative to the viewport and size of it differs in various browsers. Browser real screen estate (viewport minus tabs, toolbars, ui etc.), different algorithms for sub-pixel rendering, font rendering, size of white space around inline-block elements which depends on defult font size - these are all factors that impact viewport dimensions and there are probably more. More so, these factors vary very often with every new browser version (plus users can alter settings), so any rules derived from comparison of calculated values would probably have limited value if any.

As for handling sub-pixel values I would suggest always using Math.floor to prevent any unwanted layout breakage or adjust design to be more flexible regarding browser variations.

Do different browsers render decimal percentage sizes differently?

Yes they do.

From my memory:

In Opera, you cannot set the decimal places of the percentage so, if you set 33.3% it uses only 33% (rather annoying) (edit:Opera may have improved on that in current version as it seems)

In Firefox, if you have percentages that add up to 100%, the pixels don't always add up to the 100% of the pixels

e.g. you have a outer div with three columns all with width: 33.33333%. If the outer div has width 100px, the columns will have 33 pixels and the sum is 99 pixels and not 100.
(edit: Firefox does better than I remember. Maybe they improved)

Old IE, I cannot remember IE9 seems to work fine. The bad one of course is IE7, which rounds up (as the IE6, but who cares?). IE8/9 seem to work ok

Chrome works fine

Safari: can't remember


edit

Her one can test for oneself

http://jsfiddle.net/fTpFw/


conclusion

After I played with my fiddle in different browsers I think they all have improved. The only bad implementations (from what I want to achieve) in modern browsers is Opera and Safari. IE7 is a stopper, too. If you don't have to deal with these buggers, you could go ahead and use the percentage widths.

safari rounding down on subpixel calculations

There isn't a whole lot you can do about how different browsers render subpixels, sadly. It'd be great if we could choose how the rounding should be handled through CSS, but nope.

Simply using pixels rather then percentages would solve the problem but that's obviously not what you want. I guess you could get around with static pixels if you change the values (possible to a percentage value) through media queries.

Whenever I find myself in a similar scenario I float the last child to the right. A few additional pixels between the last and second last elements don't usually hurt as much as a few additional pixels between the last element and its parent.



Related Topics



Leave a reply



Submit