Is It Wise to Use Fractional/Decimal Pixels for Borders in CSS

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.

Are the decimal places in a CSS width respected?

If it's a percentage width, then yes, it is respected:

#outer {
width: 200px;
}

#first {
width: 50%;
height: 20px;
background-color: red;
}

#second {
width: 50.5%;
height: 20px;
background-color:green;
}

#third {
width: 51%;
height: 20px;
background-color:blue;
}
<div id="outer">
<div id="first"> </div>
<div id="second"> </div>
<div id="third"> </div>
</div>

Why can I use 1.5px as size?

"I know that 1px is the smallest unit that a computer can represent" - what does this mean?

I think there may be some confusion between different types of pixel. There are device pixels, the 'blobs' that make up a physical screen. And there are CSS pixels.

In the 'old days' often a CSS pixel and a screen pixel would match so, yes, one CSS pixel was the minimum that could be represented on the physical device.

But nowadays often several device pixels are used to represent one CSS pixel.

This means that fractions of a CSS pixel may be able to be represented with more accuracy than in the past.

Hence a CSS value such as 1.5px may get represented accurately on a device which is using say 2 physical pixels (in each direction) to represent one CSS pixel.

A warning though- different devices use different numbers of physical pixels per CSS pixel, and browsers can interpret things differently and odd little fractions of CSS pixels can get 'left behind' when the system is trying to decide how to split things.

Does CSS accept 'pixel' in decimals?

Don't look things up on W3Schools, they are a bad source. In general, when you want to know something like this, just look at the specification. Lengths are <number>s, which can include fractional values.

Can I have 12.5px font size?

A fractional px font size is perfectly valid.

Modern browsers perform layout with device-independent floating-point values, and there are few-to-no differences between running on a high resolution (2x, 1.25x, etc.) display and setting the zoom level in a browser.

You should be aware that certain values are rounded to whole pixels, such as borders, and this difference might manifest in subtle ways.

As an illustration, Firefox reports 1px for the computed border width of all these, while Chrome does not. A box made purely of border width might layout differently in Firefox and Chrome — there's a tradeoff at play here.

Also as an illustration, do a Find in Page for "px" and look at the ragged border of the highlight — it smoothly moves to the right rather than jumping at a certain point.

Edit: And Safari (on Mac) is indeed the odd one out, apparently rounding the font size to a whole number for display (but the computed value is still fractional).

document.querySelectorAll('span').forEach(span => {  const {width, height} = span.getBoundingClientRect();  span.textContent += `\t${width}x${height}`;  const {borderTopWidth} = getComputedStyle(span);  span.textContent += `\t${borderTopWidth}`;});
span {  border: 0.08em solid silver;  white-space: pre-wrap;}
<div style="font-size:12.0px"><span>font-size:12.0px</span></div><div style="font-size:12.1px"><span>font-size:12.1px</span></div><div style="font-size:12.2px"><span>font-size:12.2px</span></div><div style="font-size:12.3px"><span>font-size:12.3px</span></div><div style="font-size:12.4px"><span>font-size:12.4px</span></div><div style="font-size:12.5px"><span>font-size:12.5px</span></div><div style="font-size:12.6px"><span>font-size:12.6px</span></div><div style="font-size:12.7px"><span>font-size:12.7px</span></div><div style="font-size:12.8px"><span>font-size:12.8px</span></div><div style="font-size:12.9px"><span>font-size:12.9px</span></div><div style="font-size:13.0px"><span>font-size:13.0px</span></div><div> </div>

How do browsers deal with non-integer values for height and width?

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:

Sample Image

"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.

Should I use px or rem value units in my CSS?

TL;DR: use px.

The Facts

  • First, it's extremely important to know that per spec, the CSS px unit does not equal one physical display pixel. This has always been true – even in the 1996 CSS 1 spec.

    CSS defines the reference pixel, which measures the size of a pixel on a 96 dpi display. On a display that has a dpi substantially different than 96dpi (like Retina displays), the user agent rescales the px unit so that its size matches that of a reference pixel. In other words, this rescaling is exactly why 1 CSS pixel equals 2 physical Retina display pixels.

    That said, up until 2010 (and the mobile zoom situation notwithstanding), the px almost always did equal one physical pixel, because all widely available displays were around 96dpi.

  • Sizes specified in ems are relative to the parent element. This leads to the em's "compounding problem" where nested elements get progressively larger or smaller. For example:

      body { font-size:20px; } 
    div { font-size:0.5em; }

    Gives us:

      <body> - 20px
    <div> - 10px
    <div> - 5px
    <div> - 2.5px
    <div> - 1.25px
  • The CSS3 rem, which is always relative only to the root html element, is now supported on 99.67% of all browsers in use.

The Opinion

I think everyone agrees that it's good to design your pages to be accommodating to everyone, and to make consideration for the visually impaired. One such consideration (but not the only one!) is allowing users to make the text of your site bigger, so that it's easier to read.

In the beginning, the only way to provide users a way to scale text size was by using relative size units (such as ems). This is because the browser's font size menu simply changed the root font size. Thus, if you specified font sizes in px, they wouldn't scale when changing the browser's font size option.

Modern browsers (and even the not-so-modern IE7) all changed the default scaling method to simply zooming in on everything, including images and box sizes. Essentially, they make the reference pixel larger or smaller.

Yes, someone could still change their browser default stylesheet to tweak the default font size (the equivalent of the old-style font size option), but that's a very esoteric way of going about it and I'd wager nobody1 does it. (In Chrome, it's buried under the advanced settings, Web content, Font Sizes. In IE9, it's even more hidden. You have to press Alt, and go to View, Text Size.) It's much easier to just select the Zoom option in the browser's main menu (or use Ctrl++/-/mouse wheel).

1 - within statistical error, naturally

If we assume most users scale pages using the zoom option, I find relative units mostly irrelevant. It's much easier to develop your page when everything is specified in the same unit (images are all dealt with in pixels), and you don't have to worry about compounding. ("I was told there would be no math" – there's dealing with having to calculate what 1.5em actually works out to.)

One other potential problem of using only relative units for font sizes is that user-resized fonts may break assumptions your layout makes. For example, this might lead to text getting clipped or running too long. If you use absolute units, you don't have to worry about unexpected font sizes from breaking your layout.

So my answer is use pixel units. I use px for everything. Of course, your situation may vary, and if you must support IE6 (may the gods of the RFCs have mercy on you), you'll have to use ems anyway.

Why doesn't css border-bottom show in these inline divs when applying a fractional height?(Only Chrome)

You can use float: left; in place of display:inline-block;. It will work for any height.



Related Topics



Leave a reply



Submit