How can you find the height of text on an HTML canvas? How can you find the height of text on an HTML canvas? javascript javascript

How can you find the height of text on an HTML canvas?


UPDATE - for an example of this working, I used this technique in the Carota editor.

Following on from ellisbben's answer, here is an enhanced version to get the ascent and descent from the baseline, i.e. same as tmAscent and tmDescent returned by Win32's GetTextMetric API. This is needed if you want to do a word-wrapped run of text with spans in different fonts/sizes.

Big Text on canvas with metric lines

The above image was generated on a canvas in Safari, red being the top line where the canvas was told to draw the text, green being the baseline and blue being the bottom (so red to blue is the full height).

Using jQuery for succinctness:

var getTextHeight = function(font) {  var text = $('<span>Hg</span>').css({ fontFamily: font });  var block = $('<div style="display: inline-block; width: 1px; height: 0px;"></div>');  var div = $('<div></div>');  div.append(text, block);  var body = $('body');  body.append(div);  try {    var result = {};    block.css({ verticalAlign: 'baseline' });    result.ascent = block.offset().top - text.offset().top;    block.css({ verticalAlign: 'bottom' });    result.height = block.offset().top - text.offset().top;    result.descent = result.height - result.ascent;  } finally {    div.remove();  }  return result;};

In addition to a text element, I add a div with display: inline-block so I can set its vertical-align style, and then find out where the browser has put it.

So you get back an object with ascent, descent and height (which is just ascent + descent for convenience). To test it, it's worth having a function that draws a horizontal line:

var testLine = function(ctx, x, y, len, style) {  ctx.strokeStyle = style;   ctx.beginPath();  ctx.moveTo(x, y);  ctx.lineTo(x + len, y);  ctx.closePath();  ctx.stroke();};

Then you can see how the text is positioned on the canvas relative to the top, baseline and bottom:

var font = '36pt Times';var message = 'Big Text';ctx.fillStyle = 'black';ctx.textAlign = 'left';ctx.textBaseline = 'top'; // important!ctx.font = font;ctx.fillText(message, x, y);// Canvas can tell us the widthvar w = ctx.measureText(message).width;// New function gets the other info we needvar h = getTextHeight(font);testLine(ctx, x, y, w, 'red');testLine(ctx, x, y + h.ascent, w, 'green');testLine(ctx, x, y + h.height, w, 'blue');


Browsers are beginning to support advanced text metrics, which will make this task trivial when it's widely supported:

let metrics = ctx.measureText(text);let fontHeight = metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent;let actualHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;

fontHeight gets you the bounding box height that is constant regardless of the string being rendered. actualHeight is specific to the string being rendered.

Spec: https://www.w3.org/TR/2012/CR-2dcontext-20121217/#dom-textmetrics-fontboundingboxascent and the sections just below it.

Support status (20-Aug-2017):


You can get a very close approximation of the vertical height by checking the length of a capital M.

ctx.font = 'bold 10px Arial';lineHeight = ctx.measureText('M').width;