Skip to main content

How to use custom font for HTML5 canvas?

How to draw external font on html5 canvas?

If you want to use custom font for Konva.Text you just need to:

  1. Add font style to your page
  2. Set fontFamily attribute to required font-face.

But there is one important thing here. When you set font for DOM elements (like div or span) browsers will automatically update that elements when font is loaded. But it doesn't work the same for canvas text. You need to redraw canvas again.

Modern approach: CSS Font Loading API

The most modern way to detect when a font is loaded is to use the CSS Font Loading API, which is supported in all modern browsers.

This API provides a clean, Promise-based way to load and detect fonts without any hacks or workarounds.

import Konva from 'konva';

// Build our stage

const width = window.innerWidth;
const height = window.innerHeight;

const stage = new Konva.Stage({
  container: 'container',
  width: width,
  height: height,
});

const layer = new Konva.Layer();
stage.add(layer);

// Add a text node with default font

const text = new Konva.Text({
  x: 50,
  y: 50,
  fontSize: 40,
  text: 'A text with custom font.',
  width: 250,
  // Start with default font

  fontFamily: 'Arial'
});

// Add another text to help debug font loading

const debugText = new Konva.Text({
  x: 50,
  y: 0,
  fontSize: 16,
  text: 'Loading font...',
  fill: 'green'
});

layer.add(text);
layer.add(debugText);
layer.draw();

// First, load the font using a stylesheet link (more reliable)

const fontLink = document.createElement('link');
fontLink.href = 'https://fonts.googleapis.com/css2?family=Kavivanar&display=swap';
fontLink.rel = 'stylesheet';
document.head.appendChild(fontLink);

// Use the browser's font loading mechanism to detect when it's ready

document.fonts.ready.then(() => {
  // Check if our font is loaded

  if (document.fonts.check('1em Kavivanar')) {
    text.fontFamily('Kavivanar');
    debugText.text('Font loaded successfully!');
    // setTimeout(() => {

    //   layer.draw();

    // }, 100);

  } else {
    // Fallback - try with a small delay (common issue with some browsers)

    setTimeout(() => {
      debugText.text('Using fallback timer - attempting to set font now');
      text.fontFamily('Kavivanar');
    }, 500);
  }
}).catch(err => {
  debugText.text('Error loading font: ' + err.message);
  debugText.fill('red');
  console.error('Font loading failed:', err);
});