End of line or line break in HTML5 Canvas?

It’s tricky to do an end of line or line break in HTML5 Canvas because it’s not built-in. I’m sure one day it will be supported. Hopefully soon, but for now we have to devise some way to do it in JavaScript. We can add line-height and print by symbolic cues.

When I realized that there’s no built-in line break in HTML5 Canvas, I did it the hard way. Printing the hard way is not the good way. It wasn’t (in my case) because the outcome had random letter spacing that didn’t look natural. It took a while for me to figure out a normal looking outcome. It’s actually simpler than what I’ve tried to do before. So now I’m sharing because it was so hard to figure out, and you could be having a hard time with it too.

Set up the Canvas

<canvas id="canvas" width="300" height="300">

var canvas = document.getElementById('canvas');
var canvasContext = canvas.getContext('2d');

Print a basic Hello Canvas

The settings before the actual “printing” of the text is important to the line break. The fillStyle and textAlign are to make the outcome more distinguishable for this tutorial. The fontSize variable helps with that too. But it’s important to make a line break, which we’ll see later.

var fontSize = 20;

canvasContext.font = fontSize + "px Arial";
canvasContext.fillStyle = "#000";
canvasContext.textAlign = "left";

canvasContext.fillText("Hello Canvas", 50, canvas.height/2);

The canvas should look like this

Printing text in HTML5 Canvas JavaScript

Printing with End of Line (or Line Break)

To make an end of line or line break, we have to turn the words of “Hello Canvas” string into pieces of words inside an array. To do that, we use JavaScript’s .split() method.

var string = "Hello Canvas";
var array = string.split(" ");

// array[0] = "Hello"
// array[1] = "Canvas" 

Then we’re going to loop through the array variable and print each element. After each element is printed to the Canvas, we’ll add the line break. This is where the fontSize helps.

var x = 50;
var y = canvas.height/2;

for (var i = 0; i < array.length; i++) {
   canvasContext.fillText(array[i], x, y);
   y += fontSize;

Since .fillText requires an x and a y, we can manipulate the y value so that the next word will be printed on a lower y axis. Notice the more you add to the canvas’ y-axis the more you go down. This is the same for the x-axis. However, instead of going up and down, you go left to right. You add more to x when you want to go right, and subtract from x when you want to go left. In this case, x stays the same. To make sure that we go to the next line, we add the fontSize to the y variable, so the next word gets printed on a different y-axis.

Printing text on HTML5 Canvas JS with line break

We can give some space in between the words by adding a number. It’s like adjusting the line-height. I’m going to guess here; I’ll use 4. It’s really up to preference. There’s no rule.

y += (fontSize + 4);

Notice the space between the words. It’s not much but there’s definitely a wider gap as opposed to the previous one.

Printing text on HTML5 Canvas JS with line break or end of line with space between words

Printing End of Lines (or Line Breaks) using symbolic cues

What if we don’t want to print every word on each line? What if we just want to do an end of line on a specific part of the string? Then, we need to use symbolic cues.

We can make a custom element for the cue. You can do whatever. I recommend something more recognizable like \n or <br>

Let’s use <br>. I’m also changing from “Hello Canvas” to “Hello There Canvas”. I want to print “Hello There” on the same line but “Canvas” on the next line. So I’m going to put <br> in between “There” and “Canvas”.

var string = "Hello There<br>Canvas";
var array = string.split("<br>");

//array[0] = "Hello There"
//array[1] = "Canvas" 

Everything is the same. The only two that changed are the value of variable string and that we’re splitting the words by the symbolic cue.

The array variable will go through the for-loop. The print is as expected.

Printing end of line or line break in HTML5 Canvas JavaScript using symbolic cues.

Thoughts to go with

The value of variable fontSize is very important here. It will differ with every font style. In this case, the font style is Arial. But other fonts might have characters that are taller or shorter. So in some cases you may or may not need to add space between the words. The value of fontSize will differ in certain occasions beyond the example of this.

If you have your own way of doing End of Line (or Line Break) in Canvas, please share! If you tried my way with different font styles and font sizes, please share as well!

  • airider

    Is there a way to do this with two separate sets of text? I need to have the text formatted separately. I have a canvas where I have one set of text, stored in a database and called via php that is positioned at the top of the page, and another also from the database, which is positioned below it. Because of HTML Canvas limitations, I have to pick a “y” for the lower text that will “hopefully” be further enough down to not be overwritten by the text on top. What I’d desire is to place a couple carriage returns, just like in a word processor, between the top and lower text and the lower text would continue to get “pushed down” as the top text word count grew.

    I found this on codepen.io to handle the word wrap of each set of text. What I need is for both of these text inputs to work together while still being formatted separately by canvas text formatting

  • Anthony Kerr

    My version, you can make this a Constructor function and instantiate away.

    Engine.prototype.renderTextBox = function(stringX, splitX){
    var meta = {
    xPos: 0,
    yPos: 1,
    shape: “textBox”,
    colour: “#000000”,
    playerId: “textBox1″,
    setSplit: splitX || ” “,
    stringArray: [],
    font: “15px Arial”,
    padding: 10
    meta.stringArray = stringX.split(meta.setSplit);
    meta.stringArray.forEach(function(c, i, a){
    meta.yPos += meta.padding;
    xPos: meta.xPos,
    yPos: meta.yPos,
    shape: meta.shape,
    colour: meta.colour,
    playerId: “textBox1”,
    text: c
    }, this);

    // The main drawing for the engine
    Engine.prototype.render = function(objectX){
    var meta = this._getInfo();
    var context = meta.context;
    context = context.getContext(“2d”);
    case “fillRect”:
    context.fillStyle = objectX.colour;
    context[objectX.shape](objectX.xPos, objectX.yPos, meta.playerWidth, meta.playerHeight);
    case “arc”:
    context.fillStyle = objectX.colour;
    context.arc(objectX.xPos, objectX.yPos, 15, 0, 2*Math.PI);
    case “textBox”:
    context.fillStyle = objectX.colour;
    context.font = objectX.font;
    context.fillText(objectX.text, objectX.xPos, objectX.yPos);