Canvas Text

Canvas draws text as shapes using fillText() and strokeText(), with the font property controlling typeface, size, and style.

Drawing Text on a Canvas

Unlike HTML text, text drawn on a canvas isn't part of the DOM — it's painted onto the pixel grid, just like a rectangle or a path. The Canvas 2D API gives you two drawing methods, fillText() for solid text and strokeText() for outlined text, plus a font property that controls how the text looks before you draw it.

fillText() and strokeText()

Both methods share the same signature: fillText(text, x, y [, maxWidth]) and strokeText(text, x, y [, maxWidth]). The x and y coordinates position the text according to the current textAlign and textBaseline settings (by default, x is the left edge and y is the alphabetic baseline of the first line). The optional maxWidth compresses the text horizontally if it would otherwise be wider than that value.

Example 1: Filled and Stroked Text

<!DOCTYPE html>
<html>
<body>

<canvas id="textCanvas" width="400" height="160" style="border:1px solid #ccc;"></canvas>

<script>
const canvas = document.getElementById("textCanvas");
const ctx = canvas.getContext("2d");

ctx.font = "48px Arial";
ctx.fillStyle = "#222222";
ctx.fillText("Hello Canvas", 20, 60);

ctx.strokeStyle = "#e63946";
ctx.lineWidth = 2;
ctx.strokeText("Hello Canvas", 20, 120);
</script>

</body>
</html>

The font property accepts the same shorthand syntax as CSS font: an optional style/weight, a required size, and a required font family, such as "italic bold 32px Georgia". If you omit the size or family, the browser falls back to its default (usually 10px sans-serif), so always set both explicitly.

  • font must include both a size and a font-family, e.g. "bold 24px Verdana" — omitting either falls back to canvas defaults.
  • textAlign (start, end, left, right, center) controls how text is positioned horizontally relative to x.
  • textBaseline (top, middle, alphabetic, bottom, hanging, ideographic) controls vertical alignment relative to y.
  • measureText(text) returns a TextMetrics object so you can measure width before drawing, useful for centering text manually.
  • Canvas text does not wrap automatically — long strings must be split and drawn line by line yourself.

Example 2: Centered Text with measureText()

<!DOCTYPE html>
<html>
<body>

<canvas id="centeredCanvas" width="300" height="100" style="border:1px solid #ccc;"></canvas>

<script>
const ctx2 = document.getElementById("centeredCanvas").getContext("2d");
const w = 300, h = 100;

ctx2.font = "32px 'Trebuchet MS'";
ctx2.textAlign = "center";
ctx2.textBaseline = "middle";

ctx2.fillStyle = "#1d3557";
ctx2.fillText("Centered", w / 2, h / 2);

const metrics = ctx2.measureText("Centered");
console.log("Text width:", metrics.width);
</script>

</body>
</html>
Note: Setting textAlign = "center" and textBaseline = "middle" together, then drawing at the canvas's own center point, is the simplest way to perfectly center a label without manually calculating offsets.

Example 3: Wrapping Long Text Manually

<!DOCTYPE html>
<html>
<body>

<canvas id="wrapCanvas" width="300" height="150" style="border:1px solid #ccc;"></canvas>

<script>
function wrapText(ctx, text, x, y, maxWidth, lineHeight) {
  const words = text.split(" ");
  let line = "";

  for (const word of words) {
    const testLine = line + word + " ";
    if (ctx.measureText(testLine).width > maxWidth && line !== "") {
      ctx.fillText(line, x, y);
      line = word + " ";
      y += lineHeight;
    } else {
      line = testLine;
    }
  }
  ctx.fillText(line, x, y);
}

const ctx3 = document.getElementById("wrapCanvas").getContext("2d");
ctx3.font = "18px Arial";
wrapText(ctx3, "Canvas text does not wrap on its own, so long paragraphs need a helper function like this one.", 10, 30, 260, 24);
</script>

</body>
</html>
Note: fillText() and strokeText() are computed relative to the current font, textAlign, and textBaseline at the moment they're called — change any of those properties and redraw if the text needs to look different, since previously drawn text is just static pixels and won't update itself.
Property / MethodPurpose
ctx.fontSets style, weight, size, and family used by text methods, e.g. "bold 20px Arial"
ctx.fillText(text, x, y)Draws filled (solid) text at the given position
ctx.strokeText(text, x, y)Draws outlined (hollow) text at the given position
ctx.textAlignControls horizontal alignment relative to x (left, center, right, etc.)
ctx.textBaselineControls vertical alignment relative to y (top, middle, alphabetic, etc.)
ctx.measureText(text)Returns a TextMetrics object, useful for width and centering calculations

Exercise: Canvas Text

Which property sets the font size and family used for canvas text?