3

I'm new to HTML and JavaScript. I'm trying to learn JavaScript width() and height() method. I have set the height and width of div1 to 100px and 300px respectively.

However, when I run the code, the height and width returned by the JavaScript is 299.666666 and 99.666665 respectively. What is the reason for the discrepancy between the values I set and the ones returned?

<!DOCTYPE html>
<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
        <script>
            $(document).ready(function () {
                $("button").click(function () {
                    var txt = "";
                    txt += "Width of div: " + $("#div1").width() + "</br>";
                    txt += "Height of div: " + $("#div1").height();
                    $("#div1").html(txt);
                });
            });
        </script>
        <style>
            #div1 {
                height: 100px;
                width: 300px;
                padding: 10px;
                margin: 3px;
                border: 1px solid blue;
                background-color: lightblue;
            }
        </style>
    </head>
    <body>

        <div id="div1"></div>
        <br>

        <button>Display dimensions of div</button>

        <p>width() - returns the width of an element.</p>
        <p>height() - returns the height of an element.</p>

    </body>
</html>
halfer
  • 19,824
  • 17
  • 99
  • 186
Thor
  • 9,638
  • 15
  • 62
  • 137
  • 1
    The Fiddle displays correctly. https://jsfiddle.net/u24knzLn/ - Nothing pops up in my browser's console to indicate incorrect code either. I'm at a loss. – TRose Dec 27 '15 at 11:39
  • @TRose thanks for help out! Appreciate the effort! – Thor Dec 27 '15 at 11:45
  • 1
    I get different values depending on zoom level...have you checked that? – Paulie_D Dec 27 '15 at 12:01
  • 1
    The issue is the border, it seems it's somehow is using subpixel layout, even if it shouldn't, so it doesn't get set at 1px even if that's what it should be. Subpixel layout is in fact mostly used to make elements appear sharper when zooming. – adeneo Dec 27 '15 at 12:06
  • BTW, you did hit `CTRL-0` to make *absolutely* sure there's no zoom – adeneo Dec 27 '15 at 12:30
  • JavaScript does not have `width` and `height` methods. –  Dec 27 '15 at 13:03

4 Answers4

2

You can use parseInt method to get absolute value.

<!DOCTYPE html>
<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
        <script>
            $(document).ready(function () {
                $("button").click(function () {
                    var txt = "";
                    txt += "Width of div: " + parseInt($("#div1").width())+ "</br>";
                    txt += "Height of div: " + parseInt($("#div1").height());
                    $("#div1").html(txt);
                });
            });
        </script>
        <style>
            #div1 {
                height: 100px;
                width: 300px;
                padding: 10px;
                margin: 3px;
                border: 1px solid blue;
                background-color: lightblue;
            }
        </style>
    </head>
    <body>

        <div id="div1"></div>
        <br>

        <button>Display dimensions of div</button>

        <p>width() - returns the width of an element.</p>
        <p>height() - returns the height of an element.</p>

    </body>
</html>
Ataur Rahman Munna
  • 3,887
  • 1
  • 23
  • 34
  • This is correct, but so is OP's code. They produce identical results when I run it on my end... do you know if there's a likely reason for OP to be seeing decimals? – TRose Dec 27 '15 at 11:43
2

Although true, my initial answer was irrelevant to the question asked. As clarifications were asked in comments, while trying to address them, I discovered my initial error and, attempting to provide a proper answer I have found this answer to a similar question, to be quite relevant for the one above.

Another quite common reason for pixel scaling, mentioned by adeneo in comments below is browser scaling/zooming (Ctrl/Cmd++, Ctrl/Cmd+-, Ctrl/Cmd+0 to reset).


Despite its chosen name, browser px have nothing to do with physical, device pixels and they are not the "default" screen unit. So it needs to be calculated. It is a non-linear angular measurement:

As defined in CSS Lengths,

The reference pixel is the visual angle of one pixel on a device with a pixel density of 96dpi and a distance from the reader of an arm's length. For a nominal arm's length of 28 inches, the visual angle is therefore about 0.0213 degrees. For reading at arm's length, 1px thus corresponds to about 0.26 mm (1/96 inch).

A more detailed explanation here.

Community
  • 1
  • 1
tao
  • 82,996
  • 16
  • 114
  • 150
  • And this is relevant how? When setting a height, one would expect to get that number back, regardless of what the physical size on screen is ? – adeneo Dec 27 '15 at 11:55
  • 1
    Perhaps you missed the **it's not the default screen unit**. Therefore, it needs to be converted, therefore, rounded. In fact, the exact size is different on devices with different pixel densities. – tao Dec 27 '15 at 12:01
  • I didn't miss it, I just didn't get it? I can't for the life of me understand how this is the issue. – adeneo Dec 27 '15 at 12:03
  • [CSS Lengths](http://www.w3.org/TR/CSS21/syndata.html#length-units) might help with that. – tao Dec 27 '15 at 12:06
  • I know all this, it still doesn't explain why when you set the border to 1px it's really set to 0.909091px? maybe you could explain exactly why that is ? – adeneo Dec 27 '15 at 12:13
  • It differs from device to device, based on pixel density. On devices with a different pixel density than the reference (CSS one = 96dpi), the `screen pixel` will be different than the `reference pixel`. You see `0.909091` and I see `1`, when inspecting. It's device dependant. I don't know how to explain clearer than that :) – tao Dec 27 '15 at 12:19
  • So you're saying jQuery will return different numbers for most CSS values, based on the pixel density of the device then ? – adeneo Dec 27 '15 at 12:22
  • And wouldn't it compund, so when you set an elements width to 300px, that same device would return 270px, yet it's only in subpixels in borders that this issue is present ? – adeneo Dec 27 '15 at 12:24
  • I would be somewhat hellish if the browser changed the computed styles based on how pixels are calculated. Most of us know that a pixel isn't a pixel isn't a pixel, but the browser still returns whatever you set, *unless* you zoom or scale etc, then the browser actually changes the computed styles to subpixel layout to render more smoothly, and I would bet good money that's what the OP is seeing, probably because he inadvertently zoomed. – adeneo Dec 27 '15 at 12:42
  • You are correct, adeneo. Elements defined in `px` all use CSS `px`, the same unit that is used in media queries. When rendered, those values get scaled on zoom-in and zoom-out, while elements defined in `em` are not. Updated my answer. – tao Dec 27 '15 at 13:16
1

In general, rounding in binary can cause this.

Can't be sure about this specific case but, rounding a number in baseX isn't the same as the same number rounded after conversion to baseY. Computers do their maths with ones and zeroes, not all languages iron out the discrepancy.

Speckle
  • 103
  • 1
  • 7
1

The reason about that discrepancy is that browsers differ on zooming functions. So as tyler durden said here:

"The reason why some browsers don't zoom properly has nothing to do with sub-pixel support, it is because they are not remembering the exact position and rounding correctly. In other words, they are prematurely rounding the position and that causes the image to be mis-aligned."

In fact, for the example you are referring too, on my browsers, safari as always zooms only text!

IE, Chrome, Opera and Firefox are resizing by calculating not only the text, but also, all the elements you are using on your page (border, width,padding etc). In addition, Border AFFECTS the outside edge of your element so lets see if its rounded properly:

<!DOCTYPE html>
<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
            <script>
        $(window).ready(function () {
            $("button").click(function () {
                var txt = "";
                txt += "Width of div1: " + $(window).width() + "</br>";
                txt += "Width of div1: " + $("#div1").width() + "</br>";
                txt += "Inner left border width of div1: " + $("#div1").css("border-left-width") + "</br>";

                txt += "Height of div1: " + $("#div1").height();
                $("#div1").html(txt);
                fixSubpixelLayout($('#all-cats'), $('#all-cats .cat'));
            });
        });

    </script>
        <style>
            #div1 {
                height: 100px;
                width: 300px;
                padding: 10px;
                margin: 3px;
                border: 1px solid blue;
                background-color: lightblue;
            }
        </style>
    </head>
    <body>

        <div id="div1"></div>
        <br>

        <button>Display dimensions of div</button>

        <p>width() - returns the width of an element.</p>
        <p>height() - returns the height of an element.</p>

    </body>
</html>

well border width is changed while zooming on my chrome and firefox, but it is not on my IE!! So the reason for that "malfunction" $("#div1").width() is inside the calculation method that each browser uses while zooming.

If u want a solution for your problem you can use outline instead of border, in order to have a border unbounded from its within element.

Community
  • 1
  • 1
Vinc
  • 306
  • 1
  • 7