JavaScript Canvas - Text, Typography & SVG
Written by Ian Elliot   
Monday, 04 November 2019
Article Index
JavaScript Canvas - Text, Typography & SVG
SVG Text

SVG Text on Canvas

This is an advanced topic that uses techniques from later in the book.

Canvas text is fine for basic tasks but it lacks the typographical control needed for more advanced tasks. SVG text, on the other hand, has all of the characteristics of CSS text and is much more sophisticated. For example, you can adjust the individual positions of characters, change letter spacing, change word spacing, select kerning and so on. To find out how to do these things, all you need to do is to look up the CSS attributes needed to style text.

This is one function that will render SVG text:

async function text(ctx,x,y, text, style) {
   var svg = '<svg xmlns="" 
                             height="80" width="800">';
   svg += '<text x="0" y="0" 
dominant-baseline="text-before-edge" '; svg += style + '>' + text + '</text>'+ '</svg>'; svg = btoa(svg); var img = new Image(); img.src = 'data:image/svg+xml;base64,' + svg; await imgLoaded(img); ctx.drawImage(img, x, y); }

We also need:

function imgLoaded(img) {
   return new Promise(
                      resolve => {
                        img.onload =  () => {

Notice that we are using promises and so it is assumed that ECMA 2015 is available. Also notice that the text that you draw has to fit into an 80x800 area - you can increase the size if this is too small.

Using the function is easy:

text(ctx, x, y, text, style)

This renders the string in text on the canvas context ctx at position x,y using the style specified in style. The only problem is in specifying the SVG style in a string with single and double quotes.

For example:

text(ctx,100,100,"Hello SVG Text!",
               'font-family="symbol" font-size="20pt"');



The typographic controls are another issue. For example, you can use x="0" y="0" to set the position of the text to 0,0, but you can also supply a list of values that will be used to position each letter in the string. If you just want to add an increment then you can also use dx and dy and again specify a list. For example:

text(ctx, 50,50,"H2O is water", 'dy="0,8,-8"'); 



You can also specify a rotation for each character using rotate= and a list of angles in degrees:

text(ctx,100,100,"Hello SVG Text!",'font-family="serif" 
        font-size="20pt" rotate="90,45,60,33,22,34,55"');

The final angle applies to the remaining characters:


You can adjust the letter spacing:

text(ctx,10,100,"Hello SVG Text!",'font-family="serif" 
                  font-size="20pt" letter-spacing="4"');

This produces:


You can also adjust word spacing, kerning, and even word wrap for multline text. If you need to change the format in part of a string then use the <tspan> tag. For text to a path use <textpath>, but you will also need to set an SVG path before rendering. Look up SVG text or CSS text styling.


In chapter but not in this extract

  • Character Sets
  • Unicode
  • UTF-8
  • UTF-16 in JavaScript
  • The BMP - Basic Multilingual Plane
  • JavaScript Problem


  • Canvas text is just another example of a path to be filled or stroked using fillText or strokeText. Drawing text does not interact with or modify the current path.

  • You can set the font used via the CSS font values and the font property.

  • Line spacing has to be set manually as there is no concept of multiline text in Canvas text.

  • There is limited typographic control in Canvas text and the degree to which TextMetrics is supported is limited.

  • An alternative to using Canvas text is to use SVG text which has full typographic control.

  • Old ISO character sets are converted to Unicode UTF-8 by the browser.

  • JavaScript works with UTF-16 restricted to a single word which means you can only work directly with the Basic Multilingual Plan (BMP).

  • Unicode characters can be entered as literals using escape sequences.

  • The new Unicode functions help, but there are still some problems to overcome. In particular if you go beyond the BMP then JavaScript string functions will give you the wrong results as they don’t handle characters that correspond to two 16-bit words.

  • There is also the problem that a Unicode glyph has more than one way to specify it. The new normalize function can help with testing for equality in such cases.


Now available as a paperback or ebook from Amazon.

JavaScript Bitmap Graphics
With Canvas




  1. JavaScript Graphics
  2. Getting Started With Canvas
  3. Drawing Paths
      Extract: Basic Paths 
      Extract: Bezier Curves 
  4. Stroke and Fill
      Extract: Stroke Properties 
      Extract: Fill and Holes 
  5. Transformations
      Extract: Transformations 
  6. Text
      Extract: Text, Typography & SVG 
      Extract: Unicode 
  7. Clipping, Compositing and Effects
      Extract: Clipping & Basic Compositing 
  8. Generating Bitmaps
      Extract:  Introduction To Bitmaps
      Extract :  Animation **NEW!
  9. WebWorkers & OffscreenCanvas
      Extract: OffscreenCanvas
  10. Bit Manipulation In JavaScript
  11. Typed Arrays
  12. Files, blobs, URLs & Fetch
      Extract: Blobs & Files
      Extract: Read/Writing Local Files 
  13. Image Processing
      Extract: ImageData
      Extract: The Filter API
  14. 3D WebGL
  15. 2D WebGL
    Extract: WebGL Convolutions 






To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.





or email your comment to:

Last Updated ( Saturday, 09 November 2019 )