How to achieve $.width() with precision - javascript

How can I compute the exact width of a block element excluding padding, scroll bar, border, and margin? I know I can use $(element).width(), but jQuery does not compute the exact value because it silently rounds up the fractional part. (Please see my previous question here.)
The only way I can think of is to use .getBoundingClientRect().width and subtract what's not needed. There's got to be something better than this, but what is it?

With Javascript you can also use getComputedStyle(). Don't know about jquery alternative
var element = document.getElementById("a");
alert(window.getComputedStyle(element).width);

jQuery is not silently rounding the value. jQuery is returning the browser computed value. Since browsers can not display a fraction of a pixel the browser itself is computing a more appropriate value for the element. jQuery is actually returning the correct and most precise value.
take this code for example:
<div style="width:201px;">
<div style="width:50%;"></div> <!-- this renders as 100px, not 100.5px -->
</div>
There is 1 div with a width of 50% inside an element that is 201px wide.
based on your assumptions, each div should have a width of 100.5px. However, If you inspect the child element using any browsers development tools you will notice that it is actually being rendered as just 100px wide with no fractional value.

Related

Where is Element.clientWidth with fractional number?

MDN says that Element.clientWidth "will round the value to an integer" and I should use Element.getBoundingClientRect() instead for a fractional value. While the part with the fractional value is correct, that function has a different meaning and cannot be compared.
clientWidth gives me the inner visible width without the vertical scrollbar. getBoundingClientRect gives me the outer width including the vertical scrollbar. These are entirely different sizes.
Is this intentional? Does the MDN article know about that difference? Should that restriction be added to the cross-link? What else can I do to get the desired value, which is the visible width with a fractional value?
My problem is that I'm writing code that hides elements that won't fit in the current view, depending on the view width and the elements' width. Therefore I sum up all elements' widths and compare it with the space I have. At certain window sizes, that can lead to the element width sum of 945.4 (that fits in) and the clientWidth giving me 945 (same value but rounded down, so it's less). getBoundingClientRect however gives me 951.2 in this case which is more than is actually available for the content. In consequence, a horizontal scrollbar appears which I don't want.

Get content width of an element

offsetWidth isn't good enough for me right now, as this includes padding and border width. I want to find out the content width of the element. Is there a property for that, or do I have to take the offsetWidth and then subtract the padding and border width from the computed style?
Since this comes up first when googling but doesn't have an appropriate answer yet, here's one:
function getContentWidth (element) {
var styles = getComputedStyle(element)
return element.clientWidth
- parseFloat(styles.paddingLeft)
- parseFloat(styles.paddingRight)
}
Basically, we first get the element's width including the padding (clientWidth) and then substract the padding left and right. We need to parseFloat the paddings because they come as px-suffixed strings.
I've created a little playground for this on CodePen, check it out!
It sounds to me like you want to use getComputedStyle on the element. You can see an example of getComputedStyle vs. offsetWidth here: http://jsbin.com/avedut/2/edit
Or:
window.getComputedStyle(document.getElementById('your-element')).width;
I would suggest either scrollWidth or the clientWidth depending on whether you want to account for the scrollbar.
Check out Determining the dimensions of elements or the specification itself.
I have the similar issue where my parent element isn't the window or document... I am loading an image by Javascript and want it to center after loading.
var parent = document.getElementById('yourparentid');
var image = document.getElementById('yourimageid');
image.addEventListener('load'),function() {
parent.scrollBy((image.width-parent.clientWidth)/2,(image.height-parent.clientHeight)/2);
}
Whenever you set the src then it will scroll to the center of the image. This for me is in the context of zooming into a high res version of the image.

Getting a div's "scrollWidth" when it has an absolute positioned child-div

I have a problem getting the width of a div's content (of the content, not the div itself).
The usual approach would be Javascript's scrollWidth property, I think.
The problem: within this div, another div is positioned absolute and has a negative right value (-350px). I can't change this (it's a menu, sliding in when you click a button, overlapping other elements. It needs to be positioned like that).
The scrollWidth returns the width of the outer div's content PLUS the negative right-value (in Chrome, didn't test other browsers).
Here's a short example:
/* ... */
http://jsfiddle.net/R4Cs5/12/
But I need the content's width that is accessible by scrollbars.
Any ideas?
Please use Jquery, no plain Javascript.
Thanks in advance.
I see that your jsfiddle doesn't import any jQuery library, while you wanted to use it. Anyway, with jQuery you can use .width to get an element's width see here: jsfiddle.

Dealing with scroll bars and jquery .width() method

jQuery's .width() method doesn't seem to account for scroll bars. This is problematic for me, since I'd like to set the width of some children to equal the width of their parent. I used jQuery similar to the following:
$('#contentDiv').width($('#containerDiv').width())
In this example, #contentDiv is the element I'd like to size, and I want to set it to have the width of #containerDiv, which is its parent element. My problem is that this cuts off the side of #contentDiv, as seen in this fiddle.
In my actual code, I have several elements that I'm sizing with jQuery, which all need to fit in the scrollable div, so just setting the css of #contentDiv to 100% is not an option. What's the best way of dealing with scroll bar widths of divs in jQuery?
The best solution I found while working around this solution is this:
http://chris-spittles.co.uk/?p=531
jQuery is all powerful and everything but sometimes a small dash of native JS is all you need to render pixel perfect pages... I hope you will find this solution helpful!
UPDATED:
None of the jQuery width-finding methods account for the scroll bar. In my original example, using .innerWidth(true) LOOKS like it works, but only because it returns and object, which causes width to fail and the inner contents size themselves to fit in the available space, because the example wasn't very good. However, it's possible to write a function to compute the available space in a div with a scroll bar in it, which can then be used to position the contents as you wish.
To write that function, I took advantage of the fact that, when a div is appended to a div with a scroll bar in it, it takes up the full available width (i.e. the inner width of the parent minus the width of the scroll bar).
The function looks like this:
function noScrollWidth(div){
var measureDiv = $('<div id="measureDiv">');
div.append(measureDiv);
var width = measureDiv.outerWidth();
measureDiv.remove();
return width
};
I then use this to size my content div:
$('#contentDiv').width(noScrollWidth($('#containerDiv')));
Working fiddle.
Try this:
$('#contentDiv').width($('#containerDiv')[0].clientWidth)
For more information about that solution, see this StackOverflow answer.
Another approach I'd try is setting both elements' box-sizing property to 'border-box', and see whether setting your contentDiv's width to 100% then works the way you want.
Now that fewer projects worry about crufty old browsers anymore, 'border-box' can make things easier to work with. Be sure to test multiple browsers on multiple platforms, though, because I'm not sure they all handle scrollbars the same way.

How to calculate total width of text including the left and right bearing

I am trying to calculate the total width of a span in HTML including both the left and right bearings of the first and last characters. I have already tried Javascript's offsetWidth and jQuery's width & outerWidth functions, but neither of them return the correct value I am seeking. Here is an example of what I mean. Running in Firefox the calculated width is 135px, while measuring with the Web Developer plug-in gives an actual width of 141px.
Edit
Here is what I've tried, and here are the values it gives me:
offsetWidth = 135
jQuery.width() = 135
jQuery.outerWidth() = 135
None of them are calculating the 6px overhang on the 'f' (which would make the width 141).
Sadly, no straightforward solution exists because it is outside the realm of the box model -- the browser itself does not recognise the overhang of the letter 'f' when rendering layout. You can see this for yourself if you wrap the <span> within a <div> of width: 135px, and overflow: auto -- No scrollbars appear, the overhang is simply cut off. This is also why firebug reports the width without the overhang.
As #Aaron pointed out, the problem doesn't exist with monospaced fonts as no letters extend beyond the character's fixed-width box in those fonts.
The only way to find the real width is through pixel-based (rather than layout-based) methods. I can think of one way: draw the same text, with the same font, onto a <canvas> element, and measure the pixel width that way.
Actually, I think the problem is the font itself. I changed the jsfiddle to font-family: monospace, and it was all contained within the grey box (and calculated correctly, as a result). Even leaving it as the original font, but changing the sample to "aaa" or "mmmm" worked great. It's just the "f" glyph in that font that's blowing it for you.
Unfortunately, I don't know of a DOM attribute that accounts for that. Not sure that's much of an answer, but I don't have access to comment on the question and thought these findings might help point you in the right direction...
How about jQuery's .width()?
<span id="spanId"> ... </span>
and
var w = $('#spanId').width();

Categories