I'd like to use JavaScript to calculate the width of a string. Is this possible without having to use a monospace typeface?
If it's not built-in, my only idea is to create a table of widths for each character, but this is pretty unreasonable especially supporting Unicode and different type sizes (and all browsers for that matter).
var ww = string_width(str_Name + " "); draw_text(32, 32, str_Name)); draw_text(32 + ww, 32, "has won the game!"); The above code will get the width of the given string and then draw two lines of text, using the returned string width as a separator.
A font is often measured in pt (points). Points dictate the height of the lettering. There are approximately 72 (72.272) points in one inch or 2.54 cm. For example, the font size 72 would be about one inch tall, and 36 would be about a half of an inch.
In HTML 5, you can just use the Canvas.measureText method (further explanation here).
Try this fiddle:
/** * Uses canvas.measureText to compute and return the width of the given text of given font in pixels. * * @param {String} text The text to be rendered. * @param {String} font The css font descriptor that text is to be rendered with (e.g. "bold 14px verdana"). * * @see https://stackoverflow.com/questions/118241/calculate-text-width-with-javascript/21015393#21015393 */ function getTextWidth(text, font) { // re-use canvas object for better performance const canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas")); const context = canvas.getContext("2d"); context.font = font; const metrics = context.measureText(text); return metrics.width; } function getCssStyle(element, prop) { return window.getComputedStyle(element, null).getPropertyValue(prop); } function getCanvasFontSize(el = document.body) { const fontWeight = getCssStyle(el, 'font-weight') || 'normal'; const fontSize = getCssStyle(el, 'font-size') || '16px'; const fontFamily = getCssStyle(el, 'font-family') || 'Times New Roman'; return `${fontWeight} ${fontSize} ${fontFamily}`; } console.log(getTextWidth("hello there!", "bold 12pt arial")); // close to 86
If you want to use the font-size of some specific element myEl
, you can make use of the getCanvasFontSize
utility function:
const fontSize = getTextWidth(text, getCanvasFontSize(myEl)); // do something with fontSize here...
Explanation: The getCanvasFontSize
function takes some element's (by default: the body
's) font and converts it into a format compatible with the Context.font property. Of course any element must first be added to the DOM before usage, else it gives you bogus values.
There are several advantages to this approach, including:
textAlign
and textBaseline
.NOTE: When you add the text to your DOM, remember to also take account of padding, margin and border.
NOTE 2: On some browsers, this method yields sub-pixel accuracy (result is a floating point number), on others it does not (result is only an int). You might want to run Math.floor
(or Math.ceil
) on the result, to avoid inconsistencies. Since the DOM-based method is never sub-pixel accurate, this method has even higher precision than the other methods here.
According to this jsperf (thanks to the contributors in comments), the Canvas method and the DOM-based method are about equally fast, if caching is added to the DOM-based method and you are not using Firefox. In Firefox, for some reason, this Canvas method is much much faster than the DOM-based method (as of September 2014).
This fiddle compares this Canvas method to a variation of Bob Monteverde's DOM-based method, so you can analyze and compare accuracy of the results.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With