0

I want to measure the theoretical width of some to-be-rendered text.

I like this method for getting text width, because it doesn't mutate the DOM

function getTextWidth(text, font) {
    // re-use canvas object for better performance
    var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
    var context = canvas.getContext("2d");
    context.font = font;
    var metrics = context.measureText(text);
    return metrics.width;
}

I have a CSS description of the font

.dx-widget {
    color: #333;
    font-weight: 400;
    font-size: 14px;
    font-family: "Helvetica Neue","Segoe UI",helvetica,verdana,sans-serif;
    line-height: 1.35715;
}

How can I get in JavaScript the width that different strings would be according to these CSS rules?

I don't think I can apply this CSS class to the canvas to make it work.

theonlygusti
  • 11,032
  • 11
  • 64
  • 119
  • Your question is how to add the properties to the font variable and then run the function? Not sure how it is done properly, but you can get the style of an element that exists into a variable, modify the font style in the variable and then run the function with the modified variable. – Gergo Jul 30 '21 at 12:23
  • @Gergo how can you "get the style of an element into a variable"? – theonlygusti Aug 02 '21 at 19:02

2 Answers2

1

Ok. I created a snippet.

By assigning a dummy element style (or of a real element) to a variable it is much easier to correct the code. In the console in the Developer Tools of any browser you can enter the name of the variable and see all properties.

Test and if it works for you- use it ;)

Or as Stephen P suggested in the comments- create a new empty span and you do not have to risc changing some real visible element :)

Vote his comment. It is great improvement.

var stylee=document.getElementById('test_element').style;
stylee.color="#333";
stylee.fontWeight="400";
stylee.fontSize="14px";
stylee.fontFamily='"Helvetica Neue","Segoe UI",helvetica,verdana,sans-serif';
stylee.lineHeight="1.35715";

function getTextWidth(text, font) {
    // re-use canvas object for better performance
    var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
    var context = canvas.getContext("2d");
    context.font = font;
    var metrics = context.measureText(text);
    return metrics.width;
}

document.getElementById('result').innerText=getTextWidth('some text or variable', stylee);
<span id="test_element"></span>
<div id="result"></div>
Gergo
  • 93
  • 1
  • 7
  • 1
    You can do this without requiring that an element already exists in the page — create the span element yourself first, like ... `const span = document.createElement('span'); const stylee = span.style` ... then nothing else changes in your snippet. – Stephen P Aug 05 '21 at 16:53
  • [`context.font` is a "DOMString" apparently](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/font). HTMLElement.style is a [CSSStyleDeclaration](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration), it's surprising to me it can be used in context.font. Are you sure your code is working and returning a correct result? – theonlygusti Aug 05 '21 at 20:26
  • The dimensions really appear to be incorrect. Chrome and Edge show same value and Firefox another. Anyway.. the width of element and the calculated value using this method are different. – Gergo Aug 06 '21 at 05:43
0

By reading https://developer.mozilla.org/en-US/docs/Web/CSS/font I have understood that .font can actually specify all of the information from that CSS.

line-height must immediately follow font-size, preceded by "/", like this: "16px/3"

font-weight must precede font-size

font-family must be the last value specified

So this CSS

font-weight: 400;
font-size: 14px;
font-family: "Helvetica Neue","Segoe UI",helvetica,verdana,sans-serif;
line-height: 1.35715;

can be compressed into

font: 400 14px/1.35715 "Helvetica Neue","Segoe UI",helvetica,verdana,sans-serif;

and that property value can be used in the original canvas getTextWidth function.

theonlygusti
  • 11,032
  • 11
  • 64
  • 119