Text wrap in a element

Updated version of @mizar’s answer, with one severe and one minor bug fixed.

function getLines(ctx, text, maxWidth) {
    var words = text.split(" ");
    var lines = [];
    var currentLine = words[0];

    for (var i = 1; i < words.length; i++) {
        var word = words[i];
        var width = ctx.measureText(currentLine + " " + word).width;
        if (width < maxWidth) {
            currentLine += " " + word;
        } else {
            lines.push(currentLine);
            currentLine = word;
        }
    }
    lines.push(currentLine);
    return lines;
}

We’ve been using this code for some time, but today we were trying to figure out why some text wasn’t drawing, and we found a bug!

It turns out that if you give a single word (without any spaces) to the getLines() function, it will return an empty array, rather than an array with a single line.

While we were investigating that, we found another (much more subtle) bug, where lines can end up slightly longer than they should be, since the original code didn’t account for spaces when measuring the length of a line.

Our updated version, which works for everything we’ve thrown at it, is above. Let me know if you find any bugs!

Leave a Comment