Find the width of an auto sized element - javascript

Basically I need the width of a span. Do to the need to use several custom characters that are not found on a keyboard I am building my own "input" field, using a "div". Each character gets wrapped in a "span" tag that has an event listener attached. This will allow the user to click anywhere in the string and have the cursor move to a position after a character, it also allows them to add or delete characters in the middle of a string.
I am using "offsetLeft" and "offsetWidth" to find the right side of a character, the problem is when a character/span is clicked the "offsetWidth" is way off. So for example, if I am using a 14 pixel font an "M" will return as 35 pixels wide when it is actually 11 pixels. And there are several variations, an average sized character like an "S" will return at 26 pixels when it is actually 9. So there is variation in the sizing. Now you may wonder how I found the actual letter size and that was using Firebug. Which if Firebug can find it I would assume so can I, I just haven't figured out how. So I hope someone here knows.
I also tried using "getComputedStyle" and "currentStyle to find the width and it returns "auto". Also tried getBoundingClientRect().width it the same as offsetWidth, the difference being that it also finds the fractions of a pixel in width, so an "M" is 35.366668701171875 pixels wide, odd.
EDIT:
Based on user1289347 post I should have noted that the "offsetWidth" causes the "offsetLeft" to be off by the errant amount as well.

Try jquery width() it computes the dom width pretty well every time I've used it. http://api.jquery.com/width/
And if jquery is out of the question
Create a DIV styled with the following styles. In your JavaScript, set the font size and attributes that you are trying to measure, put your string in the DIV, then read the current width and height of the DIV. It will stretch to fit the contents and the size will be within a few pixels of the string rendered size.
HTML:
<div id="Test">
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ</div>
CSS:
#Test
{
position: absolute;
visibility: hidden;
height: auto;
width: auto;
}
JavaScript (fragment):
var test = document.getElementById("Test");
test.style.fontSize = fontSize;
var height = (test.clientHeight + 1) + "px";
var width = (test.clientWidth + 1) + "px";
This will create a seperate testable div with your test, credit here Calculate text width with JavaScript It's a lot of work but it should get you better results by operating outside of your existing markup.

Related

How to calculate character width from font size.

I'm trying to calculate the number of characters that fits in one line of a div and trim off the rest although text-overflow is an option I rather calculate the length of the string that fits in it properly. Is the font-size of a character almost equal to it's width, if not how do you calculate it's width including the text spacing and the width of a white space.
P.S. - Before flagging this question, do know I've went through most of the questions and answers and none of them were satisfactory.
One way I would do it is to check if there's enough space left in the div. To do this, you would need to create an identical div and slowly remove one character from the cloned div until the original div is bigger or equal in width to the cloned div.
divClone.textContent = text
document.body.appendChild(divClone)
while(divClone.clientHeight > originalDiv.clientHeight) {
divClone.textContent = divClone.textContent.substring(0, divClone.textContent.length-1)
}
originalDiv.textContent = divClone.textContent
You can then delete the cloned div when it's done

Resizing an arbitrary length string to fit into a fixed-size div

Having trouble finding a solution to this. I've got a "button" div 100px wide and 30px tall with a variable label. I want the font size to shrink itself so that the entire label text is always visible.
JS or CSS solutions both work for me, just no jquery.
In flash I solved this problem by checking the number of lines of text, if it's over 1 shrink the font size until it all fits in one line. Not sure if that's possible in javascript.
Edit: Not a duplicate, that person had a variable sized container so different solutions were possible.
One thing here you can do is get the label text into similar size of the div with following CSS attributes and then count it's scrollwidth, then write a javascript loop and decrease font-size by some pixels till you find it's scrollwidth is less than your desired width.
white-space: pre;
overflow-x: scroll;
Small Javascript code which I tried
// dummy divelement
var divElement = document.getElementById('#myelement')
var fontSize = 15; // Starting from 15
while(divElement.offsetWidth < divElement.scrollWidth) {
divElement.style.fontSize = fontSize + "px"
fontSize--;
}
Does this answer your question? or should I provide you whole example?

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();

How to auto resize text in fixed DIV according to the text's length?

I have a fixed width and height DIV, and I need to put text inside.
Problem is, this text can be in different lengths (letter-wise), so I dont mind to reduce its size once its overflowing.
But how can I do that?
Thanks
You can use window.getComputedStyle if you target modern browsers.
It returns a collection of all real style properties applied to an element.
When you assign your text, you can get its size and compare it with the size of the div. And reduce or increase the font size and measure again.In a few loops you should get the text in the DIV.
Here is a description: https://developer.mozilla.org/en/DOM:window.getComputedStyle
Long story short, you can't do it, since various platform and browsers render fonts differently.
And, there's no cross-browser, cross-platform method to calculate the font's rendered dimensions.
A Javascript "solution" is to check if the div is overflowing, and then bump up its size accordingly, something like
while (div.scrollHeight >= div.offsetHeight) {
div.style.height = (parseInt(fontSpan.style.fontSize) + 1) + 'px';
}

How do you find the largest font size that won't break a given text?

I'm trying to use CSS (under #media print) and JavaScript to print a one-page document with a given piece of text made as large as possible while still fitting inside a given width. The length of the text is not known beforehand, so simply using a fixed-width font is not an option.
To put it another way, I'm looking for proper resizing, so that, for example, "IIIII" would come out in a much larger font size than "WWWWW" because "I" is much skinnier than "W" in a variable-width font.
The closest I've been able to get with this is using JavaScript to try various font sizes until the clientWidth is small enough. This works well enough for screen media, but when you switch to print media, is there any guarantee that the 90 DPI I appear to get on my system (i.e., I put the margins to 0.5in either side, and for a text resized so that it fits just within that, I get about 675 for clientWidth) will be the same anywhere else? How does a browser decide what DPI to use when converting from pixel measurements? Is there any way I can access this information using JavaScript?
I would love it if this were just a CSS3 feature (font-size:max-for-width(7.5in)) but if it is, I haven't been able to find it.
The CSS font-size property accepts length units that include absolute measurements in inches or centimeters:
Absolute length units are highly dependent on the output medium, and
so are less useful than relative units. The following absolute units
are available:
in (inches; 1in=2.54cm)
cm (centimeters; 1cm=10mm)
mm (millimeters)
pt (points; 1pt=1/72in)
pc (picas; 1pc=12pt)
Since you don't know how many characters your text is yet, you may need to use a combination of javascript and CSS in order to dynamically set the font-size property correctly. For example, take the length of the string in characters, and divide 8.5 (assuming you're expecting US letter size paper) by the number of characters and that gives you the size in inches to set the font-size to for that chunk of text. Tested the font-size with absolute measurements in Firefox, Safari, and IE6 so it should be pretty portable. Hope that helps.
EDIT: Note that you may also need to play around with settings such as the letter-spacing property as well and experiment with what font you use, since the font-size setting isn't really the width of the letters, which will be different based on letter-spacing, and font, proportional to length. Oh, and using a monospace font helps ;)
I don't know of a way to do this in CSS. I think your best bet would be to use Javascript:
Put the text in a div
Get the dimensions of the div
Make the text smaller if necessary
Go back to step 2 until the text is small enough
Here's some sample code to detect the size of the div.
Here's some code I ended up using, in case someone might find it useful. All you need to do is make the outer DIV the size you want in inches.
function make_big(id) // must be an inline element inside a block-level element
{
var e = document.getElementById(id);
e.style.whiteSpace = 'nowrap';
e.style.textAlign = 'center';
var max = e.parentNode.scrollWidth - 4; // a little padding
e.style.fontSize = (max / 4) + 'px'; // make a guess, then we'll use the resulting ratio
e.style.fontSize = (max / (e.scrollWidth / parseFloat(e.style.fontSize))) + 'px';
e.style.display = 'block'; // so centering takes effect
}

Categories