38

When browsers are given widths and heights for elements that aren't integer values, how do they deal with them?

In particular,

  • At what stage do non-integer values get rounded? Do they round to the nearest integer, or truncate them?
  • When a container's children have non-integer dimensions, will there ever be instances where the sum of the child lengths or heights not equal the inner width / height of the parent element?
  • Do provided non-integer dimensions get handled differently to non-integer results of percentage-based dimensions?
  • What about non-whole values for padding and margins?
  • Edit: Is it the browsers that perform this rounding, or is it the OS? If it's the OS, does that create conditions where the browser 'thinks' items are larger than their painted area, and does that create issues with the sizing of parent containers?
Jimmy Breck-McKye
  • 2,923
  • 1
  • 22
  • 32
  • 1
    Why do you assume they're rounded by the browser ? – Denys Séguret Mar 08 '13 at 17:49
  • @dystroy - that's a very good point. I hadn't thought about OS-level handling - I'll edit my question to reflect that. – Jimmy Breck-McKye Mar 08 '13 at 17:50
  • Do you want the non-integer values to be accompanied by another unit of measure? Then of course rounding to integers will not happen directly. Still, in the end you can't display anything smaller than 1px, though the subpixels could probably be used for indicating a color fade for the next pixel(s). – Markus Deibel Mar 08 '13 at 17:59
  • I'm sure the browsers are supposed to not round the positions to integer apart in the rendering layer (if they want to). But I can't find any normative specification on that, only bug reports related to browser not being sub pixel precise... – Denys Séguret Mar 08 '13 at 18:01
  • @dystroy - I can't find a conclusive reference either. I think the answer is "browsers can certainly deal with floating point numbers, but how/when they do so is inconsistent"...I'm tempted to delete my answer. – Tim M. Mar 08 '13 at 18:03
  • @TimMedora I don't think deleting your answer would help, even if if can't be accepted now. After all your screenshot may be informative. – Denys Séguret Mar 08 '13 at 18:05
  • Related: http://stackoverflow.com/questions/15300163/how-do-browsers-deal-with-non-integer-values-for-height-and-width#15300264 – bfavaretto Mar 08 '13 at 18:12

1 Answers1

62

Assertion

Browsers are designed to deal with floating point numbers and values less than one pixel.


To see a simple example showing that browsers use floating point numbers in their calculations, create a 3% width item and look at its calculated properties in Chrome developer tools as it is resized.

You should see something like this:

enter image description here

"35.296875" can't be precisely rendered by a display that maps one pixel to one pixel in the physical display (CRT, traditional LCD). However, newer high density displays use a different ratio than 1-1 and this fractional value could conceptually be used to provide a greater degree of precision.

Even on low density displays, a fractional value could provide a hint for subpixel rendering, which uses the red, green and blue components of the pixel to make the edges of an object appear smoother than possible with whole pixel values.

But exactly what the browser will do with such numbers isn't very predictable. You can't (currently) ask a browser to make a box 31.5px wide and expect a consistent or even meaningful result. Some browsers will truncate fractional values; others round up/down.

Subpixel rendering is commonly used for text and works quite well in most/all browsers, but each browser implements this differently and there is very little a developer can do to impact how this works.

When

At what stage do non-integer values get rounded in the inheritance chain?

Most/all calculations are performed as floating point numbers and any rounding may occur late in the process, or even outside of the browser's control. For example, a browser may delegate its anti-aliasing to an OS component (such as IE9 does to Windows Direct2D and DirectWrite).

CSS transitions may be tightly integrated with OS and/or hardware acceleration. This is another case in which I think it is highly likely the floating point values are preserved by the browser and passed to the underlying layer(s).

Rounding Behavior/Errors

When a container's children have non-integer dimensions, will there ever be instances where the sum of the child lengths or heights not equal the inner width / height of the parent element?

I've seen this in older browsers (IE7) as a result of percentage calculations, where 50% + 50% > 100%. Usually it is not a problem until you try to do something more complicated. Anecdotally, I have seen "off by one pixel" bugs when attempting to precisely align HTML elements as part of an animation.

Percentages vs. other Units

Do provided non-integer dimensions get handled differently to non-integer results of percentage-based dimensions?

Do they round to the nearest integer, or truncate them?

It varies. This older answer states that they are truncated, but (in Chrome 24) I see rounding (note the example fiddle). Note my earlier comment about the differences between Chrome and Safari on the same machine.

What about non-whole values for padding and margins?

The same rules (or lack thereof) appear to apply.

Standards

I haven't found a standard definition for how floating point values should be handled in all cases. The closest relevant spec I can find talks about canvas pixels:

The handling of pixel rounding when the specified coordinates do not exactly map to the device coordinate space is not defined by this specification, except that the following must result in no visible changes to the rendering: [...list of conditions...]

Again, this is from a section dealing specifically with canvas, but it does insinuate:

  • Browsers absolutely interact with fractional pixels.
  • Actual implementations will vary.
  • Some standardization does exist.
  • Mapping to the device's display may factor into the calculation.
Community
  • 1
  • 1
Tim M.
  • 53,671
  • 14
  • 120
  • 163
  • 1
    stumbled upon this post after struggling some time with a bug where my text was dancing vertically up and down. I discovered this was caused by scrolling on a dynamic list of elements that don't have integer padding/margins. Here is a simplified code sample to demonstrate the text moving http://plnkr.co/edit/2hDDBNC9y5MGb5ZJO665?p=preview – rds Jan 07 '14 at 16:49
  • @rds - great example. I think it's safe to say that all browsers *understand* subpixel values to some degree (I can see a fractional padding value even in your example) but their behavior is unpredictable or predictably bad. I usually use integer pixel values for font size and line height, especially when I am trying to get pixel-perfect alignment across browsers. Text is especially tricky, as the rendering varies greatly between browsers and even versions of browsers. – Tim M. Jan 07 '14 at 17:10
  • If non-integer px values add up with % values, then the result might be an integer again. E.g. if you have a container with 101px width, then a child with float: left; width: 50%; padding-right: 0.5px; box-sizing: border-box;, then the child element will have exactly 50px width. That is, if the browser plays along well - which this question is all about. @TimMedora Can you or anyone confirm this for browsers other than Chrome? – donquixote Jun 14 '15 at 22:21