Are the decimal places in a CSS width respected?

HtmlCss

Html Problem Overview


Something I've been wondering for a while whilst doing CSS design.

Are decimal places in CSS widths respected? Or are they rounded?

.percentage {
  width: 49.5%;
}

or

.pixel {
  width: 122.5px;
}

Html Solutions


Solution 1 - Html

If it's a percentage width, then yes, it is respected. As Martin pointed out, things break down when you get to fractional pixels, but if your percentage values yield integer pixel value (e.g. 50.5% of 200px in the example) you'll get sensible, expected behaviour.

Edit: I've updated the example to show what happens to fractional pixels (in Chrome the values are truncated, so 50, 50.5 and 50.6 all show the same width).

Solution 2 - Html

Even when the number is rounded when the page is painted, the full value is preserved in memory and used for subsequent child calculation. For example, if your box of 100.4999px paints to 100px, it's child with a width of 50% will be calculated as .5100.4999 instead of .5100. And so on to deeper levels.

I've created deeply nested grid layout systems where parents widths are ems, and children are percents, and including up to four decimal points upstream had a noticeable impact.

Edge case, sure, but something to keep in mind.

Solution 3 - Html

Although fractional pixels may appear to round up on individual elements (as @SkillDrick demonstrates very well) it's important to know that the fractional pixels are actually respected in the actual box model.

This can best be seen when elements are stacked next to (or on top of) each other; in other words, if I were to place 400 0.5 pixel divs side by side, they would have the same width as a single 200 pixel div. If they all actually rounded up to 1px (as looking at individual elements would imply) we'd expect the 200px div to be half as long.

This can be seen in this runnable code snippet:

body {
  color:            white;
  font-family:      sans-serif;
  font-weight:      bold;
  background-color: #334;
}

.div_house div {
  height:           10px;
  background-color: orange;
  display:          inline-block;
}

div#small_divs div {
  width:            0.5px;
}

div#large_div div {
  width:            200px;
}

<div class="div_house" id="small_divs">
  <p>0.5px div x 400</p>
  <div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>
</div>
<br>
<div class="div_house" id="large_div">
  <p>200px div x 1</p>
  <div></div>
</div>

Solution 4 - Html

The width will be rounded to an integer number of pixels.

I don't know if every browser will round it the same way though. They all seem to have a different strategy when rounding sub-pixel percentages. If you're interested in the details of sub-pixel rounding in different browsers, there's an excellent article on ElastiCSS.

edit: I tested @Skilldrick's demo in some browsers for the sake of curiosity. When using fractional pixel values (not percentages, they work as suggested in the article I linked) IE9p7 and FF4b7 seem to round to the nearest pixel, while Opera 11b, Chrome 9.0.587.0 and Safari 5.0.3 truncate the decimal places. Not that I hoped that they had something in common after all...

Solution 5 - Html

They seem to round up the values to the closest integer; but Iam seeing inconsistency in chrome,safari and firefox.

For e.g if 33.3% converts to 420.945px

chrome and firexfox show it as 421px. while safari shows its as 420px.

This seems like chrome and firefox follow the floor and ceil logic while safari doesn't. This page seems to discuss the same problem

http://ejohn.org/blog/sub-pixel-problems-in-css/

Solution 6 - Html

Elements have to paint to an integer number of pixels, and as the other answers covered, percentages are indeed respected.

An important note is that pixels in this case means css pixels, not screen pixels, so a 200px container with a 50.7499% child will be rounded to 101px css pixels, which then get rendered onto 202px on a retina screen, and not 400 * .507499 ~= 203px.

Screen density is ignored in this calculation, and there is no way to paint* an element to specific retina subpixel sizes. You can't have elements' backgrounds or borders rendered at less than 1 css pixel size, even though the actual element's size could be less than 1 css pixel as Sandy Gifford showed.

[*] You can use some techniques like 0.5 offset box-shadow, etc, but the actual box model properties will paint to a full CSS pixel.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAlastair PittsView Question on Stackoverflow
Solution 1 - HtmlSkilldrickView Answer on Stackoverflow
Solution 2 - HtmlnatekoechleyView Answer on Stackoverflow
Solution 3 - HtmlSandy GiffordView Answer on Stackoverflow
Solution 4 - HtmlMartinodFView Answer on Stackoverflow
Solution 5 - HtmlagaaseView Answer on Stackoverflow
Solution 6 - HtmlOlex PonomarenkoView Answer on Stackoverflow