DEV Community

Lauri Lännenmäki
Lauri Lännenmäki

Posted on

Figma Plugin API: How to Load and Use Fonts

Working with Figma text through the Figma Plugin API is a lot trickier than you might think. All the text inside Figma files are nodes called TextNodes. Essentially, nodes are layers in Figma. With text nodes you have to think about mixed styles, missing fonts and loading fonts.

For now, we concentrate on loading fonts.

If you wish to change the content of a TextNode, you must load its font.


TL;DR

Here's one way of loading a font and manipulating text:

// Load font via async function
const myFontLoadingFunction = async () => {
  await figma.loadFontAsync({ family: "Work Sans", style: "Bold" })
}

// Another function where we use the loaded font
const myAnotherFunction = () => {
  // Create text layer
  const myTextLayer = figma.createText()
  // Set the font
  myTextLayer.fontName = { family: "Work Sans", style: "Bold" }
  // Set text to uppercase
  myTextLayer.textCase = "UPPER"
  // Set text content
  myTextLayer.characters = "This is my title"
  // Add text layer to current page in Figma
  figma.currentPage.appendChild(myTextLayer);
}

// Use font only after the Promise is resolved
myFontLoadingFunction().then(() => {
  myAnotherFunction()
})
Enter fullscreen mode Exit fullscreen mode

That's basically it. If you want to know more about this subject, just keep on reading.


Glossary

  1. About loading fonts
  2. How to load fonts
  3. What can you do with fonts and text

You can find the official Figma Plugin documentation page about TextNodes here but I believe the docs could be better and that's why I wrote this blog post.


About loading fonts

The docs tells us this important thing about text and fonts:

The important thing with text is that changing the content of a text node requires its font to be loaded and that fonts are not always available. If you attempt to change, say, fontName without first loading the font for that text node, the plugin will throw an exception.

I found out that the exception will look like this in your console.

Image of an error in console.

So, basically every time you make changes to text content or its properties, you have to load its font. Only when you're changing properties like fill colour or stroke, you do not need to load the fonts.


How to load fonts

TextNodes have a property called fontName which is a javascript object that contains the font family and font style. The default font is { family: "Roboto", style: "Regular" }. In our example we want to use Work Sans, Bold.

(As a sidenote: You can load any font thats already accessible in the Figma editor. You cannot load fonts from the internet.)

The documentation says that "Loading a font is done via figma.loadFontAsync(fontname)" and maybe for someone that is enough but, as a designer, I was a bit confused when I tried it and it didn't work.

// Like in the docs => figma.loadFontAsync(fontname)
figma.loadFontAsync({ family: "Work Sans", style: "Bold" })
Enter fullscreen mode Exit fullscreen mode

On it's own, this code isn't enough. This is when the error appears in the console. As we dive deeper into the docs we find this about the loadFontAsync property:

(loadFontAsync) Makes a font available in the plugin for use when creating and modifying text. Calling this function is necessary to modify any property of a text node that may cause the rendered text to change, including .characters, .fontSize, .fontName, etc.

And from it's signature (found in the docs) loadFontAsync(fontName: FontName): Promise<void> we can see that it returns a Promise. So, we must enchance our code by creating an "async/await" function:

const myFontLoadingFunction = async () => {
  await figma.loadFontAsync({ family: "Work Sans", style: "Bold" })
}
Enter fullscreen mode Exit fullscreen mode

After the loadFontAsync Promise is resolved, we can use the then() method that returns a new Promise and when that is a success we can do what we initially wanted.

myFontLoadingFunction().then(() => {
  // Success!

  // Add your code here to do something with the loaded font!
})
Enter fullscreen mode Exit fullscreen mode

You can read more about Promises and the then() from the MDN docs.

All the code once more:

// Load font via async function
const myFontLoadingFunction = async () => {
  await figma.loadFontAsync({ family: "Work Sans", style: "Bold" })
}

// Another function where we use the loaded font
const myAnotherFunction = () => {
  // Create text layer
  const myTextLayer = figma.createText()
  // Set the font
  myTextLayer.fontName = { family: "Work Sans", style: "Bold" }
  // Set text to uppercase
  myTextLayer.textCase = "UPPER"
  // Set text content
  myTextLayer.characters = "This is my title"
  // Add text layer to current page in Figma
  figma.currentPage.appendChild(myTextLayer);
}

// Use font only after the Promise is resolved
myFontLoadingFunction().then(() => {
  myAnotherFunction()
})
Enter fullscreen mode Exit fullscreen mode

What can you do with fonts and text

After you have your fonts loaded you can use the following properties and functions of a TextNode:

  • characters = set/write your text content
  • fontSize = set font size
  • fontName = set font family and style/weight
  • textStyleId = set TextStyle using TextStyle id
  • textCase = set text casing to uppercase etc.
  • textDecoration = set decoration to underline/strikethrough
  • letterSpacing = set letter spacing in pixels or percents
  • lineHeight = set line height in pixels or percents
  • setRangeFontSize() = set font size to characters in range
  • setRangeFontName() = set font to characters in range
  • setRangeTextCase() = set text casing to characters in range
  • setRangeTextDecoration() = set text decoration to characters in range
  • setRangeLetterSpacing() = set letter spacing to characters in range
  • setRangeLineHeight() = set line height to characters in range
  • setRangeTextStyleId() = set TextStyle to characters in range

You can check out all the TextNode properties and functions here.


Have fun developing Figma plugins 🔥 I hope you found this article helpful!

Follow me on Twitter for more Figma, CSS and Design System content 💪

Oldest comments (0)