Explain Codes LogoExplain Codes Logo

How can I use custom fonts in an HTML5 Canvas element?

html
responsive-design
canvas
font-loading
Alex KataevbyAlex Kataev·Jan 6, 2025
TLDR

Use the @font-face rule to define your custom font in CSS, then utilize document.fonts.load to ensure the font is preloaded and ready for action. Call in the big guns, fillText or strokeText, to inscribe your text onto the canvas.

@font-face { font-family: 'CustomFont'; src: url('font.woff2') format('woff2'); }
document.fonts.load('10pt CustomFont').then(() => { const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); ctx.font = '20px CustomFont'; // 'CustomFont' puts on its cape 💼 ctx.fillText('Text on Canvas', x, y); // skywrites 'Text on Canvas' });

Ensure the url in your sources points to your actual font file and CustomFont matches your font's name. x and y specify where the text lands on the canvas.

Compatibility check: Cross-browser support

Finding the right fonts for all browsers

To make sure your text is legible across all browsers, include multiple formats of the font using url('font.woff2') and format('woff2') in the @font-face:

@font-face { font-family: 'CustomFont'; src: url('font.woff2') format('woff2'), url('font.woff') format('woff'); }

Font formats explained

  • .woff2 - Ideal for modern browsers with the best compression.
  • .woff - Fallback for older browsers.
  • .ttf or .otf - Options are available, but are larger and less widely supported for web use.

Advanced text manipulation: Mastering Text Jedi

When plain text doesn't cut it

For complex situations like text wrapping or text measurement, additional libraries such as fabric.js or opentype.js can save the day offering advanced manipulation and metrics.

The canvas' secret weapon: Container divs

If you're dealing with the wrath of multiple canvas elements, use container divs to manage their positions and responsive behavior.

Housekeeping rules before drawing text

Preloading fonts: Get dressed before the party

Preload your custom fonts using document.fonts.load for optimal performance. You don't want to show up at the party in your PJs, do you? 🙈

Defining font properties in CSS

Additional font properties like font-weight and font-style can be defined to match your font files:

@font-face { font-family: 'CustomFont'; src: url('font-bold.woff2') format('woff2'); font-weight: bold; // Dress code: Bold }

Cross-origin attribute: Good neighbor policy

Set the crossorigin attribute in your font links when you invite fonts from the other side of town (external domains):

<link href="http://example.com/font.woff2" rel="stylesheet" crossorigin="anonymous"> // Pass to the new guy

One name, many fonts

When drawing text, make sure your font-family name in CSS matches the name you call when you're about to start the party on the canvas with the font property.

Managing multiple canvases

Handling delayed font loading

To fend off font loading delays, you can monitor font loading using document.fonts.ready or queue canvas operations until the star of the show is ready to perform.

Crisp text on retina displays

For retina displays, you need to scale your canvas appropriately. This method will ensure your text doesn't look like it just rolled out of bed:

let ratio = window.devicePixelRatio; canvas.width = canvas.offsetWidth * ratio; canvas.height = canvas.offsetHeight * ratio; ctx.scale(ratio, ratio); // working out the "fluffy" pixels 💪

Real-time text in games

In scenarios that require dynamic text updates, cache your text for better performance, redraw only when necessary (no busy bees 🐝), and leverage off-screen canvases for hidden computations.