Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculate text width with JavaScript

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

like image 477
Jacob Avatar asked Sep 22 '08 23:09

Jacob


People also ask

How do you find the width of a string?

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.

How is font size calculated?

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.


1 Answers

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.

el.remove()); // hackfix: don't do this! return el; } console.log(getTextWidth( "hello there!", getCanvasFontSize(createEl('span')) )); console.log(getTextWidth( "hello there!", getCanvasFontSize(createEl('h1')) )); ``` -->

More Notes

There are several advantages to this approach, including:

  • More concise and safer than the other (DOM-based) methods because it does not change global state, such as your DOM.
  • Further customization is possible by modifying more canvas text properties, such as 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).

Performance

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.

like image 195
Domi Avatar answered Sep 28 '22 06:09

Domi