Is there a way to detect if the browser has subpixel precision?

二次信任 提交于 2019-12-02 17:25:15

I'm not sure where you got the idea that IE9 is the only browser that supports fractional pixel units, but that assumption is totally incorrect.

From section 4.3 of the spec (emphasis added):

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

And defining <number>:

Some value types may have integer values (denoted by <integer>) or real number values (denoted by <number>). Real numbers and integers are specified in decimal notation only. An <integer> consists of one or more digits "0" to "9". A <number> can either be an <integer>, or it can be zero or more digits followed by a dot (.) followed by one or more digits. Both integers and real numbers may be preceded by a "-" or "+" to indicate the sign. -0 is equivalent to 0 and is not a negative number.

Therefore, per spec, the px length unit must support fractional numbers.

To prove this, take a look at this fiddle in fullscreen and use your browser's zoom function to zoom all the way in:

In this Chrome screenshot, notice that the 5.5px blue box is indeed taller than the 5px red box.


I think the confusion might stem from the fact that the non-standard element.clientHeight returns a calculated (rounded) integer value, and that rounding happens differently in different browsers.

In my fiddle, for the clientHeight of the blue <div>, IE9 and Firefox 15 at 100% zoom give 6. Chrome 22 and Opera 12 give 5. In all browsers, the value of that property changes as the user changes the browser's zoom level.

In other words, it's unreliable.

If you want to do calculations with the actual, fractional units of an element, use getComputedStyle.

var el = $('#b')[0]; // the actual DOM element
var height = parseFloat(getComputedStyle(el).height); // => 5.5

You could create an odd-sized container and drop two 50% width elements in it, and find out whether they've been split 50:50 or not.

See http://jsfiddle.net/alnitak/jzrQ6/

It returns false on Chrome 22.0.1229.79 on MacOS X 10.8.2, and true on Firefox 15.0.1. I don't have MSIE to test it with.

http://jsfiddle.net/KAW3d/1/

  • in IE6, IE7 and Opera 12.02: 100.5px + 100.5px = 200px (two 100.5px floats fit into 200px container)
  • in IE8+, Firefox 15.0.1, Chrome 22: 100.5px + 100.5px > 200px

We had to do some serious pixel-perfect calculations recently, and I needed to check whether the browser was going to support subpixel layouts. I created a test for use in Conditionizr or Modernizr using some other answers as guides:

conditionizr.add('subpixel-layout', function() {
    var $testWrap = $(
        '<div style="width: 4px; height: 2px; position: absolute; right: 0; bottom: 0;">' +
            '<div id="subpixel-layout-1" style="width: 2.5px; height: 1px; float: left;"></div>' +
            '<div id="subpixel-layout-2" style="width: 2.5px; height: 1px; float: left;"></div>' +
        '</div>'
    ).appendTo('body');

    var supported = $('#subpixel-layout-1').position().top !== $('#subpixel-layout-2').position().top;
    $testWrap.remove();
    return supported;
});

Then you can use with:

conditionizr.on('!subpixel-layout', function () {
    // subpixel layout is NOT available
});

You should be able to do the same thing in Modernizr with Modernizr.addTest(), but I didn't test it.

Obviously I'm using jQuery here, but should be pretty simple without it as well.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!