JSFiddle - React, Tailwind, and code Playground

Font Kerning & Letter Spacing: HTML Text vs SVG on Canvas

by skibulk

HTML

<div class="layer">
  <p style="font-family: Arial">Lorem ipsum dolor sit amet</p>
  <p style="font-family: Verdana">Lorem ipsum dolor sit amet</p>
  <p style="font-family: 'Times New Roman'">Lorem ipsum dolor sit amet</p>
  <p style="font-family: Georgia">Lorem ipsum dolor sit amet</p>
</div>

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" class="layer">
  <style>
    text {
      font-size: 24px;
      text-rendering: geometricPrecision;
    }
  </style>
  <text x="0" y="24" font-family="Arial">
    Lorem ipsum dolor sit amet
  </text>
  <text x="0" y="48" font-family="Verdana">
    Lorem ipsum dolor sit amet
  </text>
  <text x="0" y="72" font-family="Times New Roman">
    Lorem ipsum dolor sit amet
  </text>
  <text x="0" y="96" font-family="Georgia">
    Lorem ipsum dolor sit amet
  </text>
</svg>

<img class="layer">
<canvas class="layer" width="400" height="120"></canvas>

CSS

* {
  margin: 0;
  padding: 0;
}
body{
  position: relative;
}
.layer {
  position: absolute;
  top: 0;
  left: 0;
  
  width: 400px;
  height: 120px;
}

p {
  font-size: 24px;
  line-height: 24px;
  text-rendering: geometricPrecision;
  font-kerning: normal;
}

JavaScript

// SEE THIS: https://github.com/nodebox/opentype.js/issues/220

var svg = document.querySelector('svg');
var img = document.querySelector('img');
var canvas = document.querySelector('canvas');

// get svg data
var xml = new XMLSerializer().serializeToString(svg);

// make it base64
var svg64 = btoa(xml);
var b64Start = 'data:image/svg+xml;base64,';

// prepend a "header"
var image64 = b64Start + svg64;

// set it as the source of the img element
img.src = image64;

// draw the image onto the canvas
canvas.getContext('2d').drawImage(img, 0, 0, 400, 120);