# Shoot for the Moon

This article was published on .

Don't be half-minded when dealing with fractions and pixels. How can we ensure all browsers interpret fractions in our CSS equally?

As CSS changes and morphs over time, we must not forget that legacy browsers remain unchanged; one *gotcha* that a legacy browser might snipe you with, if left unattended, is **decimals**.

A confusing subject for the uninitiated (myself included), decimals in CSS behave in a way that might not be straightforward to some, especially when you consider the variety of browsers and their individual behaviours.

## A Bit of Prerequisite Information permalink

It’s probably worth refreshing yourself on the various rounding methods used in CSS in various browsers. Alex Kilgour wrote an excellent article on the subject, Browser Rounding and Fractional Pixels, that’s more than worth reading through and bookmarking, if only for his concise table of rounding methods used by browsers and when they’re used. I’ve summarised these different rounding methods below, but I still recommend checking out Alex’s article.

- truncate to
*x*decimals - Strips all but the first
*x*characters after the decimal.*Let x = 2*`12.3456%`

→`12.34%`

- round to
*x*decimals - Rounds the figure to
*x*decimals.*Let x = 2*`12.3456%`

→`12.35%`

- nearest integer
- Same as
round to

but rounds to the nearest integer (whole number).*x*decimals`12.3456%`

→`12%`

`12.5000%`

→`13%`

- down
- Same as
nearest integer

but always rounds*down*to the nearest integer.`12.3456%`

→`12%`

`12.9999%`

→`12%`

- sub-pixel rendering
- This is the most complicated of the different methods of dealing with decimals in CSS. I will freely admit I know very little about what’s going on with
*sub-pixel rendering*, but have drawn up a quick demo to show a little bit about how it works.

While the `width`

of each box in the above demo is technically `133.3333px`

, *sub-pixel rendering* comes into play, and its behaviour might be surprising. You might expect that the `width`

of each box would be rounded individually, creating three `133px`

-wide boxes, leaving *one* extra pixel of the full `400px`

-wide `.parent`

unaccounted for.

However, what is happening, as far as I can tell, is that the browser creates a tally of the leftover `0.3333px`

from each of the three boxes and adds that *one* extra pixel of `width`

to *one* of the three boxes. The exact mechanics of how this happens are a bit of a mystery to me *(why does the middle box receive the extra pixel?)*, but the outcome makes some rhyme and reason.

But let’s not concern ourselves with the mechanics of *sub-pixel rendering* for now, and just focus on legacy browsers that employ the less accurate methods of CSS rounding, such as down

or nearest integer.

## An Example permalink

Let’s look at an example where we’re setting a *percentage*-based value that includes decimals. *Please ignore the glaringly obvious magic number in this example!*

`.parent {`

width: 1337px;

}

.child {

width: 60.029%;

}

`.parent`

`width`

is set to`1337px`

`.child`

`width`

is set to`60.029%`

, as our target`width`

is`803px`

`1337px ÷ 100 × 60.029 = 802.58773px`

Modern browsers will utilise *sub-pixel rendering* to render a *pixel* value containing decimals; however, older browsers, like *IE8*, will **truncate** the *percentage*-based value to only **two** decimal places! This spells trouble in our particular case:

`1337px ÷ 100 × 60.02 = 802.4674px`

Even the above value is rounded to the wrong target value by a modern browser.

Due to discrepancies between browsers, we can’t be sure whether a value will receive *sub-pixel rendering*, be truncated, be rounded to the nearest integer, or even be rounded *down* (floored) to the nearest integer!

As a result, more often than not, I recommend **overshooting** your target value with your fraction, whether it be a *percentage*, *em*, or *rem* fraction

. The reason for overshooting is such that any browser’s method of rounding decimals will achieve your target value.

## Brass Tacks permalink

So let’s use the running example, and modify it to match these conditions and ensure that, no matter the rounding method used by the browser, the end-result *pixel* value is consistent.

`.parent {`

width: 1337px;

}

.child {

width: 60.06%;

}

`.parent`

`width`

is set to`1337px`

`.child`

`width`

is set to`60.06%`

`1337px ÷ 100 × 60.06 = 803.0022px`

Because the worst truncation that will occur is to `2`

decimal places, our value of `60.06%`

will satisfy each rounding method, and our target value of `803px`

will be achieved cross-browser.

It’s also worth noting that a *percentage*-based value of `60.059%`

, ever-so-slightly *less* than `60.06%`

, will result in a computed value of `802.9888px`

. This satisfies *almost* every method of rounding, but it still fails when rounding down.

By making sure our computed value **overshoots** the target value, that is to say that the decimal value is *slightly* greater than the integer value, we satisfy the conditions to round down

to our target value.

## The Takeaway permalink

When creating fractions resulting in decimals in CSS, make sure that your computed value overshoots your target value if you have to support legacy browsers.